Search code examples
javascriptknockout.jsknockout-3.0knockout-binding-handlers

Knowing where observable lives in root model in foreach/descendant bindings in knockout


This is a really niche scenario where ideally I need to be able to have a binding on a property, but be able to know where that property lives within the root view model.

So for example lets say I have the object:

{
   id: ko.observable(1),
   name: ko.observable("some user"),
   groups: [
      { id: ko.observable(1), name: ko.observable("some group") },
      { id: ko.observable(2), name: ko.observable("some group") },
   ]
}

Now the problem here is if i were to have bindings like this:

<div>
<!-- ko foreach: groups -->
    <input data-bind="value: name, custom-binding: { property: name, other: foo }" />
<!-- /ko -->
</div>

Now I need to be able to resolve name here to rootModel.groups[currentIndex].name opposed to just name. Currently I don't think there is a way to know in the binding that the property is "name" as it just sees the value, so I may need to pass this in as a string, or have a custom attribute on the object that the binding looks for. Either way I need to be able to somehow get the property path for each observable (in related to the rootModel applied in its scope) within the scope of the binding.

I know it seems crazy, and it is but it is still something I need to be able to do if at all possible. So foreach is just one scenario where the child binding scope changes and is wrapped so for all scenarios I need to be able to build a property-path for properties which are used with this custom binding.

So is there a way to do this?


Solution

  • There seemed to be no easy way to do this, so I had to write pre-processors for certain bindings to cache the scope and then apply that as a new binding at runtime (as pre processors cannot access binding context).

    Then in the actual bindings they are proxied and they lookup if there is any parent with an existing scope, then the local property is appended and cached for child lookups on the binding context.

    This is being used in:

    https://github.com/grofit/treacherous

    So feel free to look at how its done there and if there is a better solution please let me know :)