knockout / knockout

Knockout makes it easier to create rich, responsive UIs with JavaScript
http://knockoutjs.com/
Other
10.43k stars 1.52k forks source link

Need the bindingContext in a beforeChange handler ... #2595

Closed gschadow closed 1 year ago

gschadow commented 2 years ago

I think I found a hard requirement to change behavior in a beforeChange handler based on the bindingContext of where a change is coming from. I already made some changes where a beforeChange handler gets to see the newValue along with the oldValue and where the handler can return boolean false to prevent the change from going forward.

Trying to describe the reason for this as in same objects are being bound to two (or more) different html nodes. They parent node use different observables to wrap the same model object. The child nodes are bound to properties through the same observables. When a change happens, I need to know from which of the two the change originated.

I can save the bindingContext where the observable was made in the closure of my callbacks. But now I need the event to tell me what the bindingContext of the element was which just initiated the value change.

I can see the binding context somewhere in this domData thing, as follows: the valueUpdateHandler is called with the event object as argument it doesn't care about. But the event.target is our element that originated the change. I can see on that event target something like: "ko1655641582113" which I guess I am supposed to access with this ko.util.domData.

ko.utils.domData.get(arguments[0].target, "1__ko__1655641582113")

and lo and behold here I get an object with {alreadyBound: true, context: ko.bindingContext}

So I could force my way into this secret place and then get that context

ko.utils.domData.get($0, "1__ko__1655641582113").context.$parentContext.$rawData

and from there I could tell if I am in the element that should go forward with the change or not.

I am sure if anybody read this far that you'd be puzzled asking why in the hell I want to do that. But think about it, the observables are cool and all, but you sometimes need different behaviors based on where in your app the user is. In some areas they are just supposed to view, in others they can make (controlled) updates.

In other words, I know what I want is right and just, but I am wondering why it is so hard to get to what I want. For example, why the domData property is such a cryptic thing with a (timestamp) instead of a constant predictably named property. It's as if to tell me that I am making a big mistake even going there...

mbest commented 1 year ago

The logic you're trying to do should be in a binding handler, which already has access to the context. In the binding handler, you can set up subscriptions to the observables and vary the logic based on the context if you want. Generally, the view model should not contain logic that needs to know how the observables are bound in the DOM.