Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I bind a ko.observableArray of strings?

I'm trying to bind a ko.observableArray of strings to a template, but I'm unable to get the template to pick up changes in the strings inside the array.

If I bind a set of objects instead of a set of strings, I get updates to the JSON, but they don't trigger anything until I actually change the first, non-array value. I'd prefer to find an array of strings, however, as I will be able to post the data model directly back to the server without any post-processing.

How can I get the updates to my arrays of strings to trigger, and how can I ensure that they correctly trigger changes without having to update a non-array value?

If it's not possible to bind to an observable array of strings, how I can get the events to trigger when updating the objects inside of the observable array?

See the example here: http://jsfiddle.net/gcEHC/2/

In this example, array3's data will be reflected in the model when value is changed, but changes to array1 and array2's data will never show up.

JS:

var ViewModel = function() {
    this.value = ko.observable("hi")
    this.array1 = ko.observableArray(["hi", "there"]);
    this.array2 = ko.observableArray([ko.observable("hi"), ko.observable("there")]);
    this.array3 = ko.observableArray([{ data: "hi" }, { data: "there" }]);
};

ko.applyBindings(new ViewModel());

HTML:

<div class='liveExample'>   
    <p><input data-bind='value: value' /></p> 
    <div data-bind="foreach: array1">
        <p><input data-bind='value: $data' /></p> 
    </div>
    <div data-bind="foreach: array2">
        <p><input data-bind='value: $data' /></p> 
    </div>
    <div data-bind="foreach: array3">
        <p><input data-bind='value: data' /></p> 
    </div>
</div>

<pre data-bind="text: ko.toJSON($data)"></pre>
like image 408
slipheed Avatar asked Apr 01 '13 16:04

slipheed


People also ask

What is binding in knockout?

Essentially a binding or a data binding is a way to link your ViewModels to your Views(templates) and vice versa. KnockoutJS uses two-way data binding, which means changes to your ViewModel influence the View and changes to your View can influence the ViewModel.

What is Ko observableArray?

If you want to detect and respond to changes of a collection of things, use an observableArray . This is useful in many scenarios where you're displaying or editing multiple values and need repeated sections of UI to appear and disappear as items are added and removed.

For what purpose do we use foreach binding in Ko?

Purpose. The foreach binding duplicates a section of markup for each entry in an array, and binds each copy of that markup to the corresponding array item. This is especially useful for rendering lists or tables.


2 Answers

In KO 3, if you point to $rawData in the binding, the array2 example works as expected.

like image 86
user3846373 Avatar answered Oct 14 '22 13:10

user3846373


From the docs:

Simply putting an object into an observableArray doesn’t make all of that object’s properties themselves observable. Of course, you can make those properties observable if you wish, but that’s an independent choice. An observableArray just tracks which objects it holds, and notifies listeners when objects are added or removed.

You need to create an object that has an observable property (of your string). Then make an observableArray of those objects.

For example, here's an example that updates the property of an object 2 seconds after the bindings are applied:

var item = function(text) {
    var self = this;

    self.Name = ko.observable(text);
}

var vm = {
    items: ko.observableArray([
        new item('one'),
        new item('two'),
        new item('three')
        ])
}

ko.applyBindings(vm);
setTimeout(function() {
    vm.items()[1].Name('updated!');
}, 2000);

Here's a complete, runnable sample: http://jsfiddle.net/psteele/z6gbM/

like image 37
PatrickSteele Avatar answered Oct 14 '22 12:10

PatrickSteele