从当前绑定上下文中检索父属性名称/路径

时间:2014-02-09 10:11:19

标签: javascript knockout.js

这比听起来要简单得多。

想象一下,我有一个自定义绑定:

KO.bindingHandlers.custom = {
  init:function(element, valueAccessor, allBindingsAccessor, 
                context, bindingContext) {
    ...
  }
});

通过HTML标记应用,如下所示:

<div>
  <div data-bind="with: a">
    <span data-bind="custom: aa"></span>
  </div>
  <div data-bind="with: b">
    <span data-bind="custom: bb"></span>
  </div>
</div>

其中ViewModel结构为:

{
  root: {
    a: {
      aa: 100
    },
    b: {
      bb: 200
    }
  }
}

我想知道,在init函数中谁是“爸爸”,可以这么说,以便当init正在处理custom: bb绑定时,我想知道属性路径是root.b(或得到任何合适的指示)。

显然,使用bindingContext.$parent并没有帮助,因为它也包含a

尝试

到目前为止,最接近的是使用bindingContext.createChildContext并在绑定中传递父属性的名称(如下面的第一个custom绑定):

<div>
  <div data-bind="with: a">
    <span data-bind="custom: {name: 'aa', parent: 'a'}"></span>
  </div>
  <div data-bind="with: b">
    <span data-bind="custom: bb"></span>
  </div>
</div>

相当难看。

注意

请注意,嵌套级别可能会超过1 - 如果在“withcustomif之前存在嵌套的foreach绑定(您可以获得图片)

有什么想法吗?

谢谢。

1 个答案:

答案 0 :(得分:0)

我还没有真正测试过这个,但你可以从你的自定义绑定调用这样的函数来走向绑定上下文堆栈并使用===来确定父对象中的哪个属性与对象匹配当前的上下文受到约束。

var getPath = function (bindingContext) {
    var parts = [],
        prev = bindingContext,
        i, n;

    for (i = 0, n = bindingContext.$parents.length; i < n; ++i) {
        var p = bindingContext.$parents[i];
        // find which property of p.$data corresponds to prev.$data
        var properties = Object.keys(p.$data);
        var matchingProperty = ko.utils.arrayFirst(properties, function (name) {
            return ko.unwrap(p.$data[name]) === prev.$data;
        });

        parts.unshift(matchingProperty || "could not determine this part");
        prev = p;
    }

    return parts.join(".");
};

我认为它只适用于简单的with表达式。复合with表达式将击败此算法。