Communication between nested components in Knockout.js

时间:2015-10-06 08:40:36

标签: javascript knockout.js

I'm trying to use knockout custom elements in my application, but I'm stuck with one problem. I have two nested custom elements and I want them to communicate. I tried to share observable between them, but I'm constantly getting an error: Unable to process binding "template: function (){return { nodes:$componentTemplateNodes} } Message: someVariable is not defined - inner component can't access observable. How to fix this? Or maybe there is a better way to communicate between nested components? I'm using knockout 3.3.0

my code:

html:

<parent-component params="variable: someVariable">
    <child-component params="variable: someVariable"></child-component>
</parent-component>

js:

ko.components.register("parent-component", {
    viewModel: function (params) {
        this.params = params;
    },
    template: "<div data-bind='text: params.variable'></div> <!-- ko template: { nodes: $componentTemplateNodes } --><!-- /ko -->"
});

ko.components.register("child-component", {
    viewModel: function (params) {
        this.params = params;
    },
    template: "<div data-bind='text: params.variable'></div>"
});

ko.applyBindings({
    someVariable: ko.observable(true)
});

demo: http://jsfiddle.net/50zbtxe3/

4 个答案:

答案 0 :(得分:4)

还有一个选择是使用未来的 let 绑定,这将在稍后的淘汰迭代中出现。这将允许您在祖父母组件中执行以下操作:

<!-- ko let: { $parentComponent: $component } -->
<parent-component params="variable: $component.someVariable">
    <child-component params="variable: $parentComponent.someVariable"></child-component>
</parent-component>
<!-- /ko -->

基本上允许您从另一个组件访问父组件。

可以在此处找到let绑定代码: https://github.com/knockout/knockout/blob/241c26ca82e6e4b3eaee39e3dc0a92f85bc1df0c/src/binding/defaultBindings/let.js

答案 1 :(得分:2)

The thing is that "someVariable" does not exist inside the "parent-component". You should pass it to the next binding level:

ko.components.register("parent-component", {
viewModel: function (params) {
    this.params = params;
    this.someVariable = params.variable;
},
template: "<div data-bind='text: params.variable'></div> <!-- ko template: { nodes: $componentTemplateNodes } --><!-- /ko -->"
});

I've updated the jsfiddle: http://jsfiddle.net/50zbtxe3/1/

答案 2 :(得分:2)

如果您只需要简单的容器

,我建议将嵌套模板绑定到$parent范围

&#13;
&#13;
ko.components.register("parent-container", {
viewModel: function (params) {
    this.params = params;
},
template: "<div data-bind='style: { color: params.color }'>Header</div> <!-- ko template: { nodes: $componentTemplateNodes, data: $parent } --><!-- /ko -->"
});

var model = {
  someVariable: 'test'
}

ko.applyBindings();
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<parent-container params="color: 'red'">
  <div data-bind="text: someVariable">asdasdsad</div>
</parent-container>

<parent-container params="color: 'blue'">
  <div data-bind="text: someVariable2">asdasdsad</div>
</parent-container>
&#13;
&#13;
&#13;

答案 3 :(得分:1)

The problem is that the DataContext of the child-component is not the root viewmodel. So you have to reference the root viewmodel directly. Like this:

<parent-component params="variable: someVariable">
    <child-component params="variable: $root.someVariable"></child-component>
</parent-component>

The context of child-component is the viewmodel of the parent-component, which does not have a someVariable property.