I just started a new Hot Towel SPA project and I am having trouble doing binding with knockout from the ViewModel.
My view model looks like this:
define([
"services/logger",
"knockout"
],
function (logger, ko) {
var title = ko.observable("Partners");
return {
title: title,
activate: function () {
var that = this;
logger.log("Partners view activated", null, "admin.partners", false);
return true;
}
};
});
The view looks like this:
<section class="row-fluid">
<div class="span10" id="admin-content">
<h2 class="page-title" data-bind="text: title"></h2>
</div>
</section>
But the title always ends up being garbage (i.e. the code of the function, like when using the debugger: FUNCTION D(){IF(0<ARGUMENTS.LENGTH) [...])
If I change the binding to "data-bind="text: title()", it works, but I realized that this doesn't bind the observable, only the value. So when doing forms with bindings like these, it doesn't update the observable, and I can't save the value.
I found examples that seem to use the exact same code as me, but I don't understand why it doesn't work.
Christian - You figured it out yourself. I'll elaborate.
Look at the vendor bundle defined in App_Start/bundleconfig.cs and then look at the script loading near the bottom of index.cshtml (~line 29).
You'll see that all 3rd party scripts - including the knockout script - are loaded together ... before Require. That means that none of the 3rd party scripts can detect the forthcoming use of require. Therefore, they load themselves into the global namespace (window).
When RequireJS comes along, it does not know about any of these services either. So when you ask for 'ko' as a dependency, it returns null
... as you can see for yourself if you put a breakpoint where your function begins.
All of this is by design.
You can shim these services into require's equivalent of an IoC container. If you did so, require would find 'ko' and your function would work. You can begin to learn about this here. I've done it. It's not too bad.
But some of us who have been swimming in these waters for a while have decided it's too much of a PITA. So we follow Durandal's simplifying recommendation: "Load a few 3rd party libraries outside of Require and let them litter the global namespace; your more numerous application files should live within Require."
It is not that hard to choose otherwise. Just learn to shim require in your main.js and you'll be in business.