【问题标题】:How to access parent or root viewmodels from within custom binding in durandal/knockout如何从 durandal/knockout 的自定义绑定中访问父视图模型或根视图模型
【发布时间】:2013-09-16 13:06:22
【问题描述】:

这是一个澄清实现此目标的最佳方法(或任何方法!)的问题。这可能是我尝试将我的 .net 编码经验应用于这种新的做事方式的方式,但我不敢相信这对许多编码人员来说不是现实世界的问题。

所以。主视图/视图模型在页面上使用许多子视图,因为某些部分会根据用户的选择/操作而变化。这些子视图组成母版页:

<div data-bind="compose: { model: articleSection, preserveContext: true }"></div>

...在子视图中,我可以像这样引用控制主视图的根可观察对象:

<a href="#" class="btn" data-bind="css: { 'btn btn-default': true, 'btn-primary': $root.inEditMode() }, click: $root.setEditMode, enable: $root.articleSelected()">Edit</a>

但是,其中一个子视图本身有一个子子视图,它使用自定义绑定和模板进行构造,因为它是树视图,需要能够递归地构造布局。

子视图代码只是:

<div id="fancytree" data-bind="groupTree: treeGroups">
    <!--<ul data-bind="template: { name: 'itemTmpl', foreach: treeGroups }, groupTree: {}"></ul>/-->
</div>

模板只是:

    <script id="itemTmpl" type="text/html">
      <!-- Template used in labtool for tree-->
        <li>
            <span>
                <span data-bind="text: name" />
            </span>
            <ul data-bind="template: { name: 'itemTmpl', foreach: children }"></ul>
        </li>
    </script>  

自定义绑定是:

ko.bindingHandlers.groupTree = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var tm = valueAccessor();
        var tmUnwrapped = tm();
        $(element).fancytree({
            minExpandLevel: 1,
            source: tmUnwrapped,
            lazyload: function (e, data) {
                data.result = datacontext.getGroupChildren('1111');
            },
            activate: function (event, data) {
                var node = data.node;
                var tg = rootVm.selectedGroupId();
                alert(node.title);
            },
        })
    }

所以我的问题是,我无法从我的 .net 时代获得我认为的“全局变量”,这是在名为“selectedArticle”的顶级根视图模型中可观察到的。当用户单击树视图节点时,会触发“激活”功能,弹出带有正确详细信息的警报,我只是希望能够将该值放入我的根视图模型中的 observable 中,这实际上是两个从自定义绑定处理程序的绑定上下文升级。

这肯定是其他人会做的事情吧?我用谷歌搜索,直到脸色发青,但我显然错过了获得所需点击量所需的关键字或概念。在自定义绑定“激活”函数的伪代码中,我只是希望能够输入类似“root.selectedArticle = node.title”的内容,但显然 root 不能以这种方式使用,所以这就是我遇到问题的地方!

【问题讨论】:

  • 我现在不能试试这个,但bindingContext.$root 应该是你的根视图模型...
  • 不,抱歉。 var rootVm = bindingContext.$root 只会导致 rootVm 包含当前视图的视图模型:moduleId: "viewmodels/groupTree"
  • 您是否在所有compose 绑定中使用preserveContext: true 直到顶部?
  • 我不能。我显示了我在子视图中使用的确切绑定:&lt;!--&lt;ul data-bind="template: { name: 'itemTmpl', foreach: treeGroups }, groupTree: {}"&gt;&lt;/ul&gt;/--&gt;,并且无法对其进行组合绑定!
  • 模板是红鲱鱼。我发现我什至不需要它。

标签: knockout.js durandal


【解决方案1】:

您可以从绑定上下文(init/update 函数的第 5 个 参数)访问它:

init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) 
 {  
    bindingContext.$data          // current data
    bindingContext.$parent        // parent binding  
    bindingContext.$parents[0]    // same to bindingContext.$parent  
    bindingContext.$parents[1]    // parent of parent  
    bindingContext.$parentContext // same with bindingContext but from parent
    bindingContext.$root          // you root View Model  
 // ...  
 }

【讨论】:

  • 不,抱歉。 var rootVm = bindingContext.$root 只会导致 rootVm 包含当前视图的视图模型:__moduleId__: "viewmodels/groupTree"
  • 这是我的错。我有两段类似的代码,而我正在测试的那段没有“preservecontext”设置。一旦我将其更改为&lt;div data-bind="compose: { model: leftColTree, preserveContext: true }"&gt;&lt;/div&gt;,我就能够从 bindingcontext 参数访问 $root 。抱歉弄错了。
  • 接受这个答案作为更彻底的解释,这样我对将来搜索的人会更有用。
【解决方案2】:

您可以在根视图模型上订阅一个事件,并在选择文章时从绑定处理程序中触发该事件。

http://durandaljs.com/documentation/Leveraging-Publish-Subscribe.html

【讨论】:

    猜你喜欢
    • 2013-01-03
    • 2014-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-06
    • 2014-06-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多