1

I am new in knockout.js, I have tried to add and remove observable to an observableArray. I just take the first observable from the array and assign it to an input element to track the changes from the array. i.e.) When I add some observable to the observableArray it needs to be reflect in the input element.

Please refer my code below

HTML:

B[0] Value: <input data-bind="value: b"/>
<br/><br/>
<table>
    <thead>
        <tr>
            <th>A</th><th>B</th>
        </tr>
    </thead>    
    <tbody data-bind="foreach: result">
        <tr>
            <td><input data-bind="value: a()"/></td>
            <td><input data-bind="value: b()"/></td>        
        </tr> 
    </tbody>
</table>
<br/>
<button data-bind="click: add">Add</button>
<button data-bind="click: remove">Remove</button>

JS:

function generate(data) {
    self = this;
    self.a = ko.observable(data.a);
    self.b = ko.observable(data.b); 
}
var arr = [{a:1, b:2}, {a:2, b:3}, {a:3, b:4}]
var obsarr = $.map(arr, function(data){ return new generate(data); });
var obsArray = {
    result : ko.observableArray(obsarr),
    b: ko.observable(obsarr[0].b)(),
    add: function(){
        var obj = new generate({a:4, b:4});
        obsArray.result.splice(0, 0, obj);
    },    
    remove: function(){
        obsArray.result.splice(0, 1);
    }
}
ko.applyBindings(obsArray);

But when I adding the observable it doesn't reflect to the input and when I change the input value after adding observable, it reflect to the second position (B1) of the array.

Is there anything I missed or I have implement anything wrong?

Please refer the JSFiddle for the above.

Thanks in advance :-)

Updated:

Two directional changes: Two-Directional ObservableArray

2 Answers 2

2

Use a computed to return the up to date first item's b value. Don't forget to account for the case when there's no items!

obsArray.b = ko.computed(function () {
    var firstItem = obsArray.result()[0];
    if (firstItem) {
        return firstItem.b();
    }
});

JSFiddle

Also, if you want your input bindings to be two-directional don't unwrap the observable when declaring the binding. Note the lack of ().

<input data-bind="value: b"/>
Sign up to request clarification or add additional context in comments.

Comments

2

I've updated your JSFiddle.

In a couple of words:

You need not use brackets if you want to update values:

<td><input data-bind="value: a"/></td>
<td><input data-bind="value: b"/></td>    

You need a computed to retreive the first element of the observable array:

var obsarr = ko.observableArray($.map(arr, function(data){ return new generate(data); }));
var obsArray = {
    result : obsarr,
    b: ko.computed(function() {
        return obsarr()[0].b();
    }),
    ......

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.