Reputation: 3142
I have a observableArray fieldChoices
that contains observables like the following ones: { name: ko.observable('new choice') }
I want to get the Observables to notify the ObservableArray which has to notify another computed.
I am binding them like this:
<div data-bind="foreach: $parent.fieldChoices">
<div>
<i class="icon-caret-right"></i>
<input type="text" class="span8" data-bind="value: name(), test: name()" />
<i class="icon-arrow-up" data-bind="click: $parentContext.$parent.shiftChoiceUp, visible: $index() !== 0"></i>
<i class="icon-arrow-down" data-bind="click: $parentContext.$parent.shiftChoiceDown, visible: $index() !== ($parentContext.$parent.fieldChoices().length - 1)"></i>
<i class="icon-remove" data-bind="click: $parentContext.$parent.removeChoice, visible: $parentContext.$parent.fieldChoices().length > 2"></i>
</div>
</div>
I cannot get the observables to notify the observable array when the name
value changes. I tried to add a custom binding test: name()
and notify from there. The problem is that the binding is not updated when the value is changed.
How can I get this working?
EDIT : Even though there are similar questions I am trying to solve this with a custom binding. I wasn't able to find any solutions for this approach.
Upvotes: 0
Views: 2515
Reputation: 76
Your fieldChoices (observable array) gets update when items are added and taken from the array, not when the item changes values. I suggest you subscribe to each item in the array.
var thingsToDoWhenAnItemsNamePropertyChanges = function(NewValue){
alert('An items name property change to '+NewValue);
}
var arr = fieldChoices();
for(var i=0, cnt=arr.length;i<cnt;i++){
var item = arr[i];
var nm = item && item.name;
if(typeof(nm.subscribe) === 'function')nm.subscribe(thingsToDoWhenAnItemsNamePropertyChanges);
}
Or if you already loop through the items while loading them into fieldChoices then you can subscribe to each objects name property then.
Upvotes: 0
Reputation: 14995
This question doesn't make a ton of sense to me because by default what you are describing works (observables notify their subscribers when values change). You can create an extender for your observables which notify your observableArray explicitly if you want, but you probably don't want to notify the observableArray that the observable changed (because then it won't notify anyone else, because it's value hasn't changed) you probably just want to do some common function -
Create an observable array -
var myArray = ko.observableArray();
register an extender -
ko.extenders.trackChildChanges = function (target, value) {
target.subscribe(function () {
// Do some notification
});
return target;
};
And then create your observables and extend them -
function child(object) {
var self = this;
self.Id = ko.observable(id).extend({trackChildChanges: true});
self.Name = ko.observable(name)extend({trackChildChanges: true});
}
var regArray = [{ id: 1, name: 'Bill'}, {id: 2, name: 'John'}];
$.each(regArray, function(index, item) {
myArray.push(new child(item));
});
Upvotes: 1