Reputation: 69611
I'm trying to create a radio group in Knockout JS, here is the template code
<p>Selected Plan <div data-bind="text: selectedPlan"></div></p>
<div data-bind="foreach: plans">
<label>
<input type="radio" name="plan" data-bind="attr: {value: id}, checked: $root.selectedPlan"/>
<span data-bind="html: title"></span>
<div data-bind="text: desc"></div>
</label>
</div>
In the component selectePlan
and plans
are registered as follows
this.plans = ko.observableArray([/* array of plans */]);
this.selectedPlan = ko.observable('xxxxx');
I have verified that xxxxx
is a valid entry in this.plans
. Despite this an error is raised in the console
knockout.js:3391 Uncaught TypeError: Unable to process binding "foreach: function(){return plans }" Message: Unable to process binding "checked: function(){return $root.selectedPlan }" Message: Cannot read property 'selectedPlan' of undefined
It seems the $root
keyword is undefined
for some reason...
EDIT: Structure of plans
[{
id: 'xxxxx',
desc: 'This is a great plan',
title: '<strong>Save with great plan</strong>',
},
...
]
Upvotes: 0
Views: 1100
Reputation: 1707
I know this has been answered, but I'm thinking you're still wondering why $root is undefined(I would). I can see you're talking about a 'component' here and there. Might it be as simple as you just trying to get the root of the component, thus $component
?
from the knockout site:
$component
If you’re within the context of a particular component template, then $component refers to the viewmodel for that component. It’s the component-specific equivalent to $root. In the case of nested components, $component refers to the viewmodel for the closest component.
This is useful, for example, if a component’s template includes one or more foreach blocks in which you wish to refer to some property or function on the component viewmodel rather than on the current data item.
Please view the Knockout Binding Context page for more info.
Upvotes: 2
Reputation: 18515
Take a look at this example:
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<p>Selected Plan
<b><span data-bind="text: selectedPlan"></span></b>
</p>
<div data-bind="foreach: plans">
<label>
<input type="radio" name="plan" data-bind="value: title, checked: $parent.selectedPlan"/>
<span data-bind="html: title"></span>
<span data-bind="text: desc"></span>
</label>
</div>
<script type="text/javascript">
var viewModel = {
plans: ko.observableArray([
{id: 1, desc: 'Red Foo', title: 'Foo'},
{id: 2, desc: 'Blue Bas', title: 'Bas'}
]),
selectedPlan: ko.observable()
};
ko.applyBindings(viewModel);
</script>
Few changes I made:
attr
binding and did instead straight value
and checked
$parent
to get to the top level but $root
works as wellUpvotes: 1