My task is to dynamicly form "href's" for links, each time an attached observable is changed. Here is the link for an example: JS Fiddle example link
I've met two problems when achieving this:
when i try to pass some string + computed observable, i get computed function listing, instead of value of it.
<a data-bind="attr: {href : '#someHash/' + getHref(10)}">Link</a>
Link looks like:
http://fiddle.jshell.net/3DAfQ/1/show/#someHash/function h(){if(0<arguments.length)return"function"===typeof v?v.apply(d,arguments):j(Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.")),this;n||g();b.r.Wa(h);return l}
Which i find not even close to appropriate.
second, when i try to change an observable, computed depends on, link doesn't change.
<a href="#" data-bind="click: changeStoreHref(20)">change Link</a>
self.changeStoreHref = function(num)
{
self.storeHref(num);
};
Here is HTML code:
<a data-bind="attr: {href : '#someHash/' + getHref(10)}">Link</a>
<a href="#" data-bind="click: changeStoreHref(20)">change Link</a>
And knockoutjs:
function viewModel()
{
var self = this;
self.storeHref = ko.observable('ten');
self.getHref = function(id)
{
return ko.computed({
read: function()
{
self.storeHref(id);
return self.storeHref();
}
});
};
self.changeStoreHref = function(num)
{
self.storeHref(num);
};
}
ko.applyBindings(new viewModel());
I remind, that you can check this example on following link: JS Fiddle example link Thanks.
A working version might look like:
HTML:
<a data-bind="attr: {href: link}">Link</a>
<a href="#" data-bind="click: changeStoreHref">change Link</a>
JavaScript:
function viewModel()
{
var self = this;
self.storeHref = ko.observable(1);
self.link = ko.computed(function() {
return '#someHash/' + self.storeHref();
});
self.changeStoreHref = function() {
self.storeHref(self.storeHref() + 1);
};
}
ko.applyBindings(new viewModel());
Fiddle: http://jsfiddle.net/3DAfQ/6/
The reason for your first problem is that you are returning the result of the call to ko.computed()
and that is a function. Typically you would define a computed which is dependent on other observables and evaluate it via executing it:
var observable = ko.observable(); // this returns a function
var computed = ko.computed(function() { return observable; }); // this also returns a function
console.log(computed()); // logs undefined
observable('hello world'); // that call will update the computed
console.log(computed()); // logs hello world
console.log(computed); // this will log the function itself as in your exemple
The next problem is the binding of your click event handler. You bind data-bind="click: changeStoreHref(20)"
. When the HTML is parsed by ko it executes changeStoreHref(20)
and binds against the result which is undefinded
. And as a side effect, it already sets self.storeHref
to 20.
If you have a scenario where you need to parametrize a click binding then you have to return a function:
HTML:
<a data-bind="attr: {href: link}">Link</a>
<a href="#" data-bind="click: changeStoreHref('test')">change Link</a>
JavaScript:
function viewModel() {
var self = this;
self.storeHref = ko.observable(1);
self.link = ko.computed(function () {
return '#someHash/' + self.storeHref();
});
self.changeStoreHref = function (para) {
return function () {
self.storeHref(para);
}
};
}
ko.applyBindings(new viewModel());
Fiddle: http://jsfiddle.net/dfLaK/1/