I'm trying to create a simple knockout computed observable following the viewmodal pattern in the Hottowel SPA template. What is the best way to do this?
I originally had something like this:
define(['services/logger'], function (logger) {
var vm = {
activate: activate,
title: 'Home View',
testField: ko.observable("This is a test"),
testComputedField: ko.computed(getComputed, this)
};
return vm;
//#region Internal Methods
function getComputed() {
return "Computed: " + this.testField();
}
function activate() {
logger.log('Home View Activated', null, 'home', true);
return true;
}
//#endregion
});
but this results in an error, though I'm not 100% sure why
TypeError: this.testField is not a function
So with a bit of trial and error I got to this:
define(['services/logger'], function (logger) {
var vm = {
activate: activate,
title: 'Home View',
testField: ko.observable("This is a test")
};
vm.testComputedField = ko.computed(getComputed, vm);
return vm;
//#region Internal Methods
function getComputed() {
return "Computed: " + this.testField();
}
function activate() {
logger.log('Home View Activated', null, 'home', true);
return true;
}
//#endregion
});
But I'm not sure this is a very pretty way of doing this; I'm obviously not grokking the module pattern used for viewmodels in HotTowel very well. So my questions are:
Why doesn't my original method work? Are there any better or alternate ways to define\structure the viewmodel than my second method?
Mutex, this is the general pattern I am using, it is working well for me.
I use function expressions and local scoped variables for the KO bindings, and function declarations for the Durandal specific methods (activated, viewAttached, etc.). The vm object needs to be after the function expressions. Eliminates the need to use 'this' everywhere.
define(['services/logger'], function (logger) {
var testField = ko.observable("This is a test");
var getComputed = ko.computed(function () {
return "Computed: " + testField();
});
function activate() {
logger.log('Home View Activated', null, 'home', true);
return true;
}
var vm = {
activate: activate,
title: 'Home View',
testField: testField,
testComputedField: getComputed
};
return vm;
});
NOTE: This is for the HotTowel SPA template