Skip to content

Descendant bindings of if, with, etc. should have a dependency on the parent condition#2234

Merged
mbest merged 4 commits intomasterfrom
2226-deferUpdates-if-binding-2
Jun 7, 2017
Merged

Descendant bindings of if, with, etc. should have a dependency on the parent condition#2234
mbest merged 4 commits intomasterfrom
2226-deferUpdates-if-binding-2

Conversation

@mbest
Copy link
Copy Markdown
Member

@mbest mbest commented May 2, 2017

… so that updates happen in the right order when using deferred updates.

See discussion in #2226

…ency on the parent condition so that updates happen in the right order when using deferred updates.
@mbest mbest added this to the 3.5.0 milestone May 2, 2017
@mbest mbest changed the title Descendant bindings of if, with, etc. have a dependency on the parent condition Descendant bindings of if, with, etc. should have a dependency on the parent condition May 2, 2017
@fastfasterfastest
Copy link
Copy Markdown

With these changes, it appears that descendant bindings will have a dependency on the ancestor binding. In #2226 (comment) you voiced concern about that, but with these changes it appears that every descendant binding will be re-evaluated when an ancestor binding is re-evaluated even if the ancestor binding value doesn't change.

The changes I proposed in #2226 (comment) caused dependent bindings to have a dependency, not on the ancestor binding, but on the ancestor binding value - and therefore doesn't (needlessly) re-evaluate descendant bindings if the ancestor binding value doesn't change.

In the following example, the text binding doesn't need to get re-evaluated whenever the if binding is re-evaluated - it only needs to get re-evaluated when the value of condition changes. The text binding only needs to have a dependency on the value of condition not on the "full" if binding.

<div data-bind="if: condition">
   <span data-bind="text: new Date().valueOf()"></span>
</div>

http://jsfiddle.net/fastfasterfastest/xjg6j2xr/2/ is a sample showing the current (3.4.2) behavior. It has a "compound" condition made up of two sub-conditions and you can set the sub-conditions. It shows timestamps when text nodes are (re-)evaluated. Notice how the descendant binding of the if binding does not get re-evaluated (and thus the timestamp doesn't change) as long as the value of condition doesn't change and even though some of condition's dependencies change.

http://jsfiddle.net/fastfasterfastest/xjg6j2xr/3/ shows the same sample using the changes I proposed in #2226 (comment) - same behavior as in 3.4.2, the descendant binding of the if binding does not get re-evaluated (and thus the timestamp doesn't change) as long as the value of condition doesn't change and even though some of condition's dependencies change.

I think with the changes proposed here, the descendant bindings of the if binding do get re-evaluated (and thus the timestamp changes) even though the value of condition doesn't change. (If you have a pre-build version available w/ the changes in this pull request I could make another fiddle.)
I think, as you mentioned before, this is a performance concern.

A minor detail: new ko.bindingContext(ko.bindingContext.inheritParentVm, bindingContext, null, function() { ifCondition(); }) is (probably) equivalent to and can be bindingContext.extend(function() { ifCondition(); return null; })). Maybe a little clearer and then no need to expose ko.bindingContext.inheritParentVm

@fastfasterfastest
Copy link
Copy Markdown

Just to clarify - it is the descendant binding's value that should have a dependency on the ancestor binding's value. The descendant binding per se, or the descendant binding context, should not have a dependency on the ancestor binding.

I outlined a way to implement that in #2226 (comment) and the sample http://jsfiddle.net/fastfasterfastest/0u1qx24p/13/ has that implementation.

@mbest
Copy link
Copy Markdown
Member Author

mbest commented May 3, 2017

I'll try my changes with your fiddle. I'm pretty sure it will work properly. Putting the dependency in the binding context also creates a dependency in the binding values since they depend on the context.

@fastfasterfastest
Copy link
Copy Markdown

Putting the dependency in the binding context also creates a dependency in the binding values since they depend on the context

Yes, but doing so causes, I believe, the descendant bindings to be (needlessly) re-evaluated when the ancestor bindings' dependencies change. I may be incorrect, but if not then the descendant bindings will be re-evaluated even if the ancestor binding's value doesn't change.

@mbest
Copy link
Copy Markdown
Member Author

mbest commented May 5, 2017

Looks like I still have some work to do.

It works as expected with deferUpdates = false: http://jsfiddle.net/mbest/xjg6j2xr/4/
but not with deferUpdates = true: http://jsfiddle.net/mbest/xjg6j2xr/5/

@fastfasterfastest
Copy link
Copy Markdown

The implementation I provided in http://jsfiddle.net/fastfasterfastest/0u1qx24p/13/ and discussed in #2226 (comment) works, I believe. Unfortunately I haven't done a pull request but if you make a diff of the "custom" knockout that fiddle uses against 3.4.2 you'll see the changes.

@mbest
Copy link
Copy Markdown
Member Author

mbest commented May 6, 2017

I figured out why my change works differently between the deferred/non-deferred scenarios. I've opened another issue to track it: #2240.

@fastfasterfastest
Copy link
Copy Markdown

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants