【问题标题】:Knockout custom binding not updating淘汰赛自定义绑定未更新
【发布时间】:2015-11-11 15:47:45
【问题描述】:

请检查我做错了什么。

当我在 javascript 中创建控件时,我的自定义绑定处理程序的更新部分不会执行。我有一个在表中创建一行的 Add 函数。绑定到自定义绑定的控件会执行更新部分,但不会执行随后添加的控件。

HTML

<div id="collapse-programHead" class="panel-collapse collapse">
            <div class="panel-body">
                <table class="cv">
                     <thead>
                        <tr>
                            <th>Programme</th>
                            <th>Core Module Count</th>
                            <th>Core SAQA Credit</th>
                            <th>Elective Module Count</th>
                            <th>Elective SAQA Credit</th>
                            <th>Credit</th>
                        </tr>
                    </thead>
                    <tbody data-bind="foreach: ProgrammeHead">
                        <!-- ko if: isActive -->
                        <tr>
                            <td><select data-bind="options: programmes, optionsText: 'Programme', value: ProgrammeID, optionsValue:'ProgrammeID', optionsCaption:''"></select></td>
                            <td><input type="text" readonly="true" data-bind="value:ModuleCount, offeringCount:$root.programmeOfferingCount"/></td>

                            <td><input type="text"/></td>
                            <td><input type="text"/></td>
                            <td><input type="text"/></td>
                            <td><input type="text" data-bind="value: Credit"/></td>
                            <td class="tinyTD"><a class="removeRow" id="ProgrammeHead" title="Delete item" href="javascript:void(0)"></a></td>
                            <td class="hideTD"><input type="hidden" data-bind="value: CVId" /></td>
                            <td class="hideTD"><input type="hidden" data-bind="value: ProgrammeID" /></td>
                            <td class="hideTD"><input type="hidden" data-bind="value: ProgrammeOfferingID" /></td>
                            <td class="hideTD"><input type="hidden" data-bind="value: ManagementLoadID" /></td>
                        </tr>
                        <!-- /ko -->
                    </tbody>
                </table>
                <a title="Add row" id="a2" href="javascript:void(0)" data-bind="click: addRow.bind($data, 'programHead')"><label>Add row</label></a>
            </div>
        </div>

ko.bandingHandler

ko.bindingHandlers.offeringCount = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            return { controlsDescendantBindings: true };
        },
        update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            var value = ko.unwrap(valueAccessor)
            var id = ko.unwrap(bindingContext.$data.ProgrammeID);

            var item = programmes().filter(function (i) {
                return i.ProgrammeID() == id;
            })
            if (item.length > 0) {
                var count = ko.unwrap(item[0].ProgrammeOfferingCount);
                bindingContext.$data.ModuleCount(count);
            }
        }
    };

程序头添加

self.ProgrammeHead.push({ 'ManagementLoadID': '', 'CVId': '', 'ModuleCount': count, 'ProgrammeID': '', 'ProgrammeOfferingID': '', 'Credit': '', 'isActive': active });

【问题讨论】:

  • html 可能是复制/粘贴交易,但它是无效的; addRow 链接将显示在每一行之后,但您也不能将锚元素放在与&lt;tr&gt; 元素相同的级别。此外,您的 &lt;tbody&gt; 元素未关闭。
  • 根据定义,自定义绑定的更新回调将在绑定值更改时调用(在您的情况下 $root.programmeOfferingCount 更改)。我可能是错的,但是.. 看起来您正在使用自定义绑定来完成通常使用计算的 observables 完成的事情。小提琴会有所帮助......
  • @dperry 是的,我故意没有复制所有 html,但是代码中的所有标签等都是有效的。
  • @Righardt,标签无效;只有 &lt;tr&gt; 元素可以是 &lt;tbody&gt; 元素的子元素,你的 for 循环中有一个 &lt;a&gt; 作为 &lt;tr&gt; 的兄弟。
  • @dperry,我知道。我只复制了部分 html 以显示前两个 &lt;td&gt;。在&lt;tr&gt; 中还有一些&lt;td&gt;&lt;a&gt;&lt;/tbody&gt;&lt;/table&gt; 之外,因此 --- Visual Studio 中的 html 是正确的。我将更新 html 以反映 html 在 vs 中的外观

标签: knockout.js custom-binding bindinghandlers


【解决方案1】:

valueAccessor 参数是一个返回绑定值的函数。如果绑定的值是可观察的,那么您还必须“解包”可观察的以获得实际值。在您的代码中,您没有正确解开值。应该是:

var value = ko.unwrap(valueAccessor());

update 函数的内容充当ko.computed 的主体,因此与computed dependency tracking 一样工作:

因此,Knockout 不仅会在评估程序第一次运行时检测依赖关系 - 它每次都会重新检测它们。这意味着,例如,依赖关系可以动态变化:依赖关系 A 可以确定计算出的 observable 是否还依赖于 B 或 C。然后,只有当 A 或您当前选择的 B 或 C 发生变化时,才会重新评估它。您不必声明依赖项:它们是在运行时根据代码的执行确定的。

【讨论】:

  • 当我ko.unwrap(valueAccessor);ko.unwrap(valueAccessor()) 时,value = undefined。这可能是我问题的根源吗?
  • 由于valueAccessor 是一个函数,我看不出它怎么可能是未定义的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-13
  • 2014-01-08
  • 1970-01-01
  • 2013-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多