Вы находитесь на странице: 1из 5

Home Download / Install Tutorials Live examples Documentation Forum Source

Getting started Observable Arrays


1. How KO works and what If you want to detect and respond to changes on one object, you’d use observables. If you want to detect
benefits it brings and respond to changes of a collection of things, use an observableArray. This is useful in many
2. Downloading and installing
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.
Observables
1. Creating view models with
Example
observables
2. Working with observable var myObservableArray = ko.observableArray();    // Initially an empty
arrays myObservableArray.push('Some value');            // Adds the value and

Computed observables
1. Using computed observables To see how you can bind the observableArray to a UI and let the user modify it, see the simple list
2. Writable computed observables
example.
3. How dependency tracking works
4. Pure computed observables
5. Reference Key point: An observableArray tracks which objects are in the array, not the
state of those objects
Bindings Simply putting an object into an observableArray doesn’t make all of that object’s properties
Controlling text and themselves observable. Of course, you can make those properties observable if you wish, but that’s an
appearance independent choice. An observableArray just tracks which objects it holds, and notifies listeners when
1. The visible and hidden
objects are added or removed.
bindings
2. The text binding
3. The html binding
Prepopulating an observableArray
4. The class and css bindings If you want your observable array not to start empty, but to contain some initial items, pass those items as
5. The style binding an array to the constructor. For example,
6. The attr binding

Control flow // This observable array initially contains three objects


1. The foreach binding var anotherObservableArray = ko.observableArray([
2. The if and ifnot bindings     { name: "Bungle", type: "Bear" },
    { name: "George", type: "Hippo" },
3. The with and using bindings
    { name: "Zippy", type: "Unknown" }
4. The let binding ]);
5. The component binding
6. Binding lifecycle events

Working with form fields


Reading information from an observableArray
1. The click binding Behind the scenes, an observableArray is actually an observable whose value is an array (plus,
2. The event binding observableArray adds some additional features described below). So, you can get the underlying
3. The submit binding JavaScript array by invoking the observableArray as a function with no parameters, just like any other
4. The enable and disable
observable. Then you can read information from that underlying array. For example,
bindings
5. The value binding
6. The textInput binding alert('The length of the array is ' + myObservableArray().length);
7. The hasFocus binding alert('The first element is ' + myObservableArray()[0]);
8. The checked binding
9. The options binding
Technically you can use any of the native JavaScript array functions to operate on that underlying array, but
10. The selectedOptions
binding normally there’s a better alternative. KO’s observableArray has equivalent functions of its own, and
11. The uniqueName binding they’re more useful because:

Rendering templates
1. The template binding
Binding syntax 1. They work on all targeted browsers. (For example, the native JavaScript indexOf function doesn’t
1. The data-bind syntax work on IE 8 or earlier, but KO’s indexOf works everywhere.)
2. The binding context
2. For functions that modify the contents of the array, such as push and splice, KO’s methods
automatically trigger the dependency tracking mechanism so that all registered listeners are notified of
Creating custom bindings
the change, and your UI is automatically updated which means there is a significant difference
1. Creating custom bindings
between using KO’s methods (i.e., observableArray.push(...) ) and JavaScript native array
2. Controlling descendant bindings
3. Supporting virtual elements methods (i.e., observableArray().push(...)) as the latter don’t send any notification to the
4. Custom disposal logic array’s subscribers that its content has changed.
5. Preprocessing: Extending the
binding syntax The rest of this page describes observableArray’s functions for reading and writing array information.

Components indexOf
1. Overview: What components
The indexOf function returns the index of the first array item that equals your parameter. For example,
and custom elements offer
2. Defining and registering myObservableArray.indexOf('Blah') will return the zero-based index of the first array entry that
components equals Blah, or the value -1 if no matching value was found.
3. The component binding
4. Using custom elements slice
5. Advanced: Custom component
The slice function is the observableArray equivalent of the native JavaScript slice function (i.e., it
loaders
returns the entries of your array from a given start index up to a given end index). Calling
Further techniques myObservableArray.slice(...) is equivalent to calling the same method on the underlying array
1. Loading and saving JSON data (i.e., myObservableArray().slice(...)).
2. Extending observables
3. Deferred updates Manipulating an observableArray
4. Rate-limiting observables
5. Unobtrusive event handling observableArray exposes a familiar set of functions for modifying the contents of the array and
6. Using fn to add custom notifying listeners.
functions
7. Microtasks pop, push, shift, unshift, reverse, sort, splice
8. Asynchronous error handling
All of these functions are equivalent to running the native JavaScript array functions on the underlying array,
and then notifying listeners about the change:
Plugins
1. The mapping plugin push( value ) — Adds a new item to the end of array.
pop() — Removes the last value from the array and returns it.
More information unshift( value ) — Inserts a new item at the beginning of the array.
1. Browser support shift() — Removes the first value from the array and returns it.
2. Getting help
reverse() — Reverses the order of the array and returns the observableArray (not the
3. Links to tutorials & examples
underlying array).
4. Usage with AMD using
RequireJs (Asynchronous sort() — Sorts the array contents and returns the observableArray. The default sort is
Module Definition) alphabetical, but you can optionally pass a function to control how the array should be sorted. See the
example under sorted below.
splice() — Removes and returns a given number of elements starting from a given index. For
example, myObservableArray.splice(1, 3) removes three elements starting from index
position 1 (i.e., the 2nd, 3rd, and 4th elements) and returns them as an array.

For more details about these observableArray functions, see the equivalent documentation of the
standard JavaScript array functions.

sorted and reversed


sorted() — Returns a sorted copy of the array. This is preferable to sort if you want to leave the
observable array in its original order but need to display it in a specific order.

The default sort is alphabetical, but you can optionally pass a function to control how the array should
be sorted. Your function should accept any two objects from the array and return a negative value if
the first argument is smaller, a positive value is the second is smaller, or zero to treat them as equal.
For example, to sort an array of ‘person’ objects by last name, you could write:

var mySortedArray = ko.pureComputed(function () {


    return myObservableArray.sorted(function (left, right) {
        return left.lastName === right.lastName ? 0
             : left.lastName < right.lastName ? -1
             : 1;
    });
});

reversed() — Returns a reversed copy of the array.

replace, remove and removeAll


observableArray adds some more useful methods that aren’t found on JavaScript arrays by default:

replace( oldItem, newItem ) — Replaces the first value that equals oldItem with
newItem.
remove( someItem ) — Removes all values that equal someItem and returns them as an array.
remove( function (item) { return item.age < 18; } ) — Removes all values
whose age property is less than 18, and returns them as an array.
removeAll( ['Chad', 132, undefined] ) — Removes all values that equal 'Chad',
123, or undefined and returns them as an array.
removeAll() — Removes all values and returns them as an array.

destroy and destroyAll (Note: Usually relevant to Ruby on Rails developers


only)
The destroy and destroyAll functions are mainly intended as a convenience for developers using
Ruby on Rails:

destroy( someItem ) — Finds any objects in the array that equal someItem and gives them a
special property called _destroy with value true.
destroy( function (someItem) { return someItem.age < 18; } ) — Finds any
objects in the array whose age property is less than 18, and gives those objects a special property
called _destroy with value true.
destroyAll( ['Chad', 132, undefined] ) — Finds any objects in the array that equal
'Chad', 123, or undefined and gives them a special property called _destroy with value true.
destroyAll() — Gives a special property called _destroy with value true to all objects in the
array.

So, what’s this _destroy thing all about? It’s only really interesting to Rails developers. The convention in
Rails is that, when you pass into an action a JSON object graph, the framework can automatically convert
it to an ActiveRecord object graph and then save it to your database. It knows which of the objects are
already in your database, and issues the correct INSERT or UPDATE statements. To tell the framework to
DELETE a record, you just mark it with _destroy set to true.

When Knockout renders a foreach binding with the parameter includeDestroyed: false set, it
will hide any objects marked with _destroy equal to true. So, you can have some kind of “delete”
button that invokes the destroy(someItem) method on the array, and this will immediately cause the
specified item to vanish from the visible UI. Later, when you submit the JSON object graph to Rails, that
item will also be deleted from the database (while the other array items will be inserted or updated as usual).

Determining if a property is an observableArray


In some scenarios, it is useful to programmatically determine if you are dealing with an observableArray.
Knockout provides a utility function, ko.isObservableArray to help with this situation.

Delaying and/or suppressing change notifications


Normally, an observableArray notifies its subscribers immediately, as soon as it’s changed. But if an
observableArray is changed repeatedly or triggers expensive updates, you may get better
performance by limiting or delaying change notifications. This is accomplished using the rateLimit
extender like this:

// Ensure it notifies about changes no more than once per 50-milliseco


myViewModel.myObservableArray.extend({ rateLimit: 50 });

Tracking array changes


Although you can subscribe to and access an observableArray just like any other observable,
Knockout also provides a super-fast method to find out how an observable array has changed (i.e., which
items were just added, deleted, or moved). You subscribe to array changes as follows:

obsArray.subscribe(fn, thisArg, "arrayChange");

The main advantages of subscribing to changes:

Performance is O(1) in most cases, i.e., there’s basically no performance implication at all, because
for straightforward operations, (push, splice, etc.) Knockout supplies the change log without
running any difference algorithm. Knockout only falls back on an algorithm if you’ve made an arbitrary
change without using a typical array mutation function.

The change log just gives you the items that actually changed.

Here are examples of how the changes are reported:

var myArray = ko.observableArray(["Alpha", "Beta", "Gamma"]);


 
myArray.push("Delta");
// Changes: [{ index: 3, status: 'added', value: 'Delta' }]
// New value: ["Alpha", "Beta", "Gamma", "Delta"]
 
myArray.pop();
// Changes: [{ index: 3, status: 'deleted', value: 'Delta' }]
// New value: ["Alpha", "Beta", "Gamma"]
 
myArray.splice(1, 2, "Omega");
// Changes:
// [{ index: 1, status: 'deleted', value: 'Beta' },
//  { index: 1, status: 'added', value: 'Omega' },
//  { index: 2, status: 'deleted', value: 'Gamma' }]
// New value: ["Alpha", "Omega"]
 
myArray.reverse();
// Changes:
// [{ index: 0, moved: 1, status: 'deleted', value: 'Alpha' },
//  { index: 1, moved: 0, status: 'added', value: 'Alpha' }]
// New value: ["Omega", "Alpha"]

As shown above, the changes are reported as a list of added and deleted values. The indexes for deleted
items refer to the original array, and the indexes for added items refer to the new array.
When items are re-ordered, as shown in the last example above, you will also get moved information. You
can choose to ignore the moved information and just interpret it as the original Alpha being deleted and a
different Alpha being added to the array’s end. Or you can recognize that the moved information tells you
that you can think of the added and deleted values being the same item that just changes position (by
matching up the indexes).

An observableArray has array tracking enabled at construction, but you can extend any other
subscribable (i.e. ko.observable and ko.computed) as follows:

trackable = ko.observable().extend({trackArrayChanges: true});

Home Download / Install Tutorials Live examples Documentation Forum Source

(c) knockoutjs.com

Вам также может понравиться