Knockout should better handle arrays of observables #482

merged 6 commits into from Sep 24, 2013


None yet

5 participants

mbest commented May 15, 2012

Some problems I've noticed:

  1. foreach unwraps the observable before binding so that the inner context can't get notified of changes to the observable. Instead the inner context will get completely re-rendered if the observable changes. This is especially a problem if the observable is an array.
  2. observableArray.remove treats an observable as a predicate function and totally does the wrong thing. destroy has the same problem.
bdukes commented May 16, 2012

+1, I'm having the same issue. See

mbest commented Jun 8, 2012

To fix item 1, I think we need #485 completed. I'll schedule this for after 2.2.


patch to improve behavior of $data via new binding variable $nameTBD

JessevanAssen and others added some commits May 13, 2013
@JessevanAssen @mbest JessevanAssen Added an extra condition to make sure that observables are compared c…
…orrectly within an array. `typeof observable == "function"` returns true for observables, so they are treated like a predicate instead of value. With this check, the observables are compared like values.
@mbest mbest Add tests showing proper behavior when removing or "destroying" obser…
…vables in an observable array.
@JessevanAssen @mbest JessevanAssen Exposed the $item variable within a foreach binding. $item refers to …
…the raw, potentially wrapped value, where $data does not.
@mbest mbest Don't unwrap observable array items in the foreach binding; instead l…
…et the binding context manage it. The result of this change is that if the observable is updated, only the underlying binding are updated (using the new observable view model system) instead of the whole template (re-rendering and re-bindings the elements).

Add tests for this change and the previous $item addition.
mbest commented Aug 27, 2013

I've added code to fix this (based on #969 by @JessevanAssen):

  1. foreach binding passes the array item directly to the binding context instead of unwrapping it first. This works now because of the observable view model support from #485. If an observable item is updated, the inner bindings are updated instead of the whole template.
  2. foreach binding provides an $item value that's equal to the raw array item (before unwrapping). This means you can use a two-way binding to the observable (see #708).
  3. remove and destroy in observableArray check for observables and handle them as values instead of predicate functions.
@mbest mbest referenced this pull request Aug 27, 2013

3.0.0 release planning #1050

mbest commented Sep 12, 2013

After reviewing #999, I think it might be better to include a generic context property for the raw, potentially wrapped view model instead of having $item for just the foreach binding.


The falconjs project implements a $view--might this be similar to the generic context property you are thinking of?

mbest added some commits Sep 12, 2013
@mbest mbest Use $rawData in place of $item for referencing an observable view mod…
…el. $rawData will work for any observable view model, not just for ones in an array.
@mbest mbest Remove $dataFn from the binding context because $rawData works fine a…
…s a replacement.
mbest commented Sep 13, 2013

Thanks, @NickLeippe, for the suggestion. I decided to go with $rawData. I was also able to replace $dataFn with $rawData when extending a context, so I removed $dataFn.

@SteveSanderson SteveSanderson merged commit 2848bcd into master Sep 24, 2013

This looks great - thanks very much!

@SteveSanderson SteveSanderson deleted the 482-arrays-of-observables branch Sep 24, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment