Inside a knockout.js binding expression, I can use the $data
, $parent
, and $root
pseudovariables. How can I get the equivalent of those pseudovariables when I'm using a ko.computed
observable declared in JavaScript?
I've got a parent viewmodel with a collection of children, and the parent viewmodel has a selectedChild
observable. Given that, I can use databinding expressions to add a CSS class to whichever child is currently selected:
<ul data-bind="foreach: children">
<li data-bind="text: name,
css: {selected: $data === $root.selectedChild()},
click: $root.selectChild"></li>
</ul>
<script>
vm = {
selectedChild: ko.observable(),
children: [{name: 'Bob'}, {name: 'Ned'}],
selectChild: function(child) { vm.selectedChild(child); }
};
ko.applyBindings(vm);
</script>
But my viewmodels are going to get more complex, and I'd like "am I selected?" to be able to do more than just adding a single CSS class to a single element. I really want to make an isSelected
computed property on the child viewmodel, so I can then add other computed properties that depend on it.
I've tried just writing JavaScript that refers to $data
and $root
, on the off-chance that knockout might define those variables and somehow have them be in scope when it calls my computed
evaluator function:
{
name: 'Bob',
isSelected: ko.computed(function(){ return $data === $root.selectedChild(); })
}
But no such luck: inside my evaluator function
, both $data
and $root
are undefined
.
I've also tried using ko.contextFor
inside my evaluator, since it does give access to $data
and $root
. Unfortunately, inside my evaluator function, contextFor
also always returns undefined
. (I didn't hold out high hopes for this strategy anyway -- it's not clear how well knockout would be able to track the dependencies if I had to go behind its back like this.)
I could always manually set a property on each child viewmodel that refers back to the parent viewmodel. But I know that knockout has the ability to do this for me, and I'd like to at least explore whether I can use its mechanisms before I go writing my own.
It seems like it should be possible to translate the above binding expression to a computed observable -- after all, that's what knockout already does:
The other neat trick is that declarative bindings are simply implemented as computed observables.
But how do I go about dealing with the $data
and $root
pseudovariables when I'm writing my own computed observable?
See Question&Answers more detail:
os