Knockout custom binding not updating

2019-09-12 08:04发布

问题:

Please check what I am doing wrong.

The update part of my custom bindinghandler does not executes when I create a control in javascript. I have an Add function that create a row in a table. Controls that are bound to the custom binding does executes the update part but not controls that are subsequently added.

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);
            }
        }
    };

ProgrammeHead Add

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

回答1:

The valueAccessor parameter is a function that returns the bound value. If the bound value is an observable, then you must also "unwrap" the observable to get the real value. In your code, you haven't unwrapped the value properly. It should be:

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

The contents of the update function act as the body of a ko.computed and so works just like the computed dependency tracking:

So, Knockout doesn’t just detect dependencies the first time the evaluator runs - it redetects them every time. This means, for example, that the dependencies can vary dynamically: dependency A could determine whether the computed observable also depend on B or C. Then, it will only be re-evaluated when either A or your current choice of B or C changes. You don’t have to declare dependencies: they’re determined at runtime from the code’s execution.