最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - knockout.js get parent observable - Stack Overflow

programmeradmin0浏览0评论

Is it possible to get parent observable in knockout? Like I have

<div data-bind="parent: {...}">
   <div data-bind="child: {...}">
      ...
   </div>
</div>

I want to get access to parent in child but not in the markup but in the code. How can I achieve in a standard knockout way?

UPDATE I have found a simple way to achieve this by simply accessing the last argument of custom handler like this:

ko.bindingHandlers.custom = {
  init: function (element, valueAccessor, allBindingsAccessor, vm, bindingContext) {
     console.log(bindingContext.$parent);
  }
}

Is it possible to get parent observable in knockout? Like I have

<div data-bind="parent: {...}">
   <div data-bind="child: {...}">
      ...
   </div>
</div>

I want to get access to parent in child but not in the markup but in the code. How can I achieve in a standard knockout way?

UPDATE I have found a simple way to achieve this by simply accessing the last argument of custom handler like this:

ko.bindingHandlers.custom = {
  init: function (element, valueAccessor, allBindingsAccessor, vm, bindingContext) {
     console.log(bindingContext.$parent);
  }
}
Share Improve this question edited Mar 12, 2014 at 11:02 lukas.pukenis asked Mar 12, 2014 at 10:14 lukas.pukenislukas.pukenis 13.6k13 gold badges49 silver badges83 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 3

You can use $parent to access the parent item:

<div data-bind="parent: {...}">
   <div data-bind="child: {...}">
      <span data-bind="text: $parent.someObservable()"></span>
      <span data-bind="text: somefunction($parent.someObservable())"></span>
   </div>
</div>

The most simple way it to past parent object to child model as a parameter (pointer) when child object constructed. But it more standard javascript way then knockout

var Parent = function (item) {
    var self = this;

    this.value = ko.observable(item.value);
    this.child = new Child(item.child, self);
}

var Child = function (item, parent) {
    var self = this;

    this.parent = parent;
    this.value = ko.observable(item.value);
}

and HTML markup will look like

This is <b><span data-bind="text: value"></span></b>

<div data-bind="with: child">
    This is <b><span data-bind="text: value"></span></b>
    <br/>
    This is <b><span data-bind="text: parent.value"></span></b> of <b><span data-bind="text: value"></span></b>
</div>

JSFIDDLE

To prevent big amount of code mapping plugin could be used and it will be more knockout way

var Parent = function (item) {
    var self = this;

    var map = {
        'child': {
            update: function(options) {
                return new Child(options.data, self);
            }
        }
    }

    ko.mapping.fromJS(item, map, self);
}

var Child = function (item, parent) {
    var self = this;

    this.parent = parent;

    ko.mapping.fromJS(item, null, self);
}

JSFIDDLE

And the most knockout way - it to create custom binding that will controls descendant bindings. In this way you can extend child context with extra properties.

ko.bindingHandlers.withParent = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // Make a modified binding context, with a extra properties, and apply it to descendant elements

        ko.mapping.fromJS({
            parent: bindingContext.$rawData
        }, null,valueAccessor());

        var childBindingContext = bindingContext.createChildContext(valueAccessor, null, null);

        ko.applyBindingsToDescendants(childBindingContext, element);
        // Also tell KO *not* to bind the descendants itself, otherwise they will be bound twice
        return { controlsDescendantBindings: true };
    }
};

Model

var Parent = function (item) {
    var self = this;

    var map = {
        'child': {
            update: function(options) {
                return new Child(options.data);
            }
        }
    }

    ko.mapping.fromJS(item, map, self);
}

var Child = function (item, parent) {
    var self = this;
    ko.mapping.fromJS(item, null, self);
}

and HTML

This is <b><span data-bind="text: value"></span></b>

<div data-bind="withParent: child">
    This is <b><span data-bind="text: value"></span></b>
    <br/>
    This is <b><span data-bind="text: parent.value"></span></b> of <b><span data-bind="text: value"></span></b>
    <br/>
    <input type="button" value="Test from code" data-bind="click: test"/>
</div>

JSFIDDLE

But personaly me not like this approach, because using together with 'with', 'foreach' or 'tempalate' bindings it could cause errors like

Message: You cannot apply bindings multiple times to the same element.

发布评论

评论列表(0)

  1. 暂无评论