I am trying to put together a demo to use knockout-es5 plugin to simplifying the models that are using revealing module pattern. ViewModel1 is original Knockout model and it works fine. ViewModel2 is an attempt to use knockout-es5 plugin. Running into few things
JS Fiddle
var NS = NS || {};
$(function () {
NS.ViewModel1 = function (first, last) {
var
firstName = ko.observable(first),
lastName = ko.observable(last),
fullName = ko.computed(function () {
return firstName() + " " + lastName();
}),
doSomething = function (n) {
lastName(lastName() + " " + n);
}
;
return {
firstName: firstName,
lastName: lastName,
fullName: fullName,
doSomething: doSomething
};
};
NS.ViewModel2 = function (first, last) {
var
firstName = first,
lastName = last,
fullName1 = ko.computed(function () {
// Changed values are not reflected
return firstName + " " + lastName;
}),
fullName2 = ko.computed(function () {
// Should not work
return this.firstName + " " + this.lastName;
}),
doSomething = function (n) {
// Doesn't work
lastName += " " + n;
// Works
// this.lastName += " " + n;
}
;
var retObj = {
firstName: firstName,
lastName: lastName,
fullName1: fullName1,
fullName2: fullName2,
doSomething: doSomething
};
ko.track(retObj);
ko.defineProperty(retObj, 'fullName3', function () {
// Changed values are not reflected
return firstName + " " + lastName;
});
ko.defineProperty(retObj, 'fullName4', function () {
// Works
return this.firstName + " " + this.lastName;
});
return retObj;
};
var vm1 = new NS.ViewModel1("John", "Doe");
ko.applyBindings(vm1, document.getElementById("observableSection"));
var vm2 = new NS.ViewModel2("Jane", "Doe");
ko.applyBindings(vm2, document.getElementById("withoutObservableSection"));
setTimeout(function () {
vm1.firstName("John 1");
vm2.firstName = "Jane 1";
}, 2000);
setTimeout(function () {
vm1.doSomething(2);
vm2.doSomething(2);
}, 4000);
});
It did not work because you linked JS directly from github. See updated fiddle that works: http://jsfiddle.net/tkirda/Wznkm/1/
The reason for that not working, is because Github indicates that content type is "text/plain" and not "application/x-javascript".
Content-Type:text/plain; charset=utf-8
Access-Control-Allow-Origin:https://render.github.com
Therefore browsers do not execute this code. I guess they did it so that people stop hotlinking files from GitHub.
UPDATE: In your case lastName is changed, add console.log and you will see it's new value.
doSomething = function (n) {
// Doesn't work
lastName += " " + n;
console.log(lastName);
// Works
// this.lastName += " " + n;
}
However it is not used by model because when you did assign them to retObj, you passed only values and not reference. Because string is value type. When you work with functions, they are of reference type. So you just updated local variable, but your model is not bound to that variable.
var retObj = {
firstName: firstName,
lastName: lastName,
fullName1: fullName1,
fullName2: fullName2,
doSomething: doSomething
};
I hope that makes sense.
I'm not sure what your question is, but yes it won't work with the pattern you are trying to use.
I like the idea of knockout-es5, but the current API it exposes has some issues that can really get you in trouble if you deviate from their pattern.
Another issue is, if you pass this.property
to some other viewmodel with the goal of that other viewmodel being able to subscribe to the observable, or update the observable, then it obviously won't work. You'll just be passing the current value. You have to remember to get the actual observable for your property in this situation. Using good old knockout, you know you are passing the observable itself when you access the property.
The project is young, so hopefully these API issues will be resolved. But right now, it requires the developer to remember too many things to get it right.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With