如何使用自定义绑定?

时间:2010-12-29 19:44:13

标签: jquery knockout.js

我有一个很大的viewModel,我想将状态更新(“read”/“unread”)发布到服务器而不发布整个模型。

我所做的是创建一个自定义绑定,如下所示:

ko.bindingHandlers.statusUpdater = {
    update: function(element, valueAccessor) {
        console.log(element);
    }
};

在模板中:

<div data-bind='template: { name: "contactsListTemplate", data: viewModel.conversations.conversationlist }'> </div>

<script type="text/html" id="contactsListTemplate">
 <table>
  <tbody>
   {{each(i, conversation) $data}}
    <tr>
     <td>
      <input type="checkbox" data-bind="checked: read, statusUpdater: conversation_id" />
     </td>
    </tr>
   {{/each}}
  </tbody>
 </table>
</script>

对于自定义绑定,我只对Updates感兴趣,我认为允许我做的是使用KnockoutJS检测更新,并确定哪个项目已更新,以便我可以获取该项ID和新统计信息,然后将其发布到服务器。

正在发生的事情是customBinding是console.log ging单个复选框修改的每个复选框。这意味着我更改了一个复选框,所有3个复选框都通过ko.bindingHandlers.statusUpdater登录到控制台。

我考虑过将click事件添加到数据绑定中,但这似乎不像自定义绑定那样干净。或许我想用自定义绑定做的不是他们的目的吗?

思想?

1 个答案:

答案 0 :(得分:4)

这样做的原因是因为每次更新模型值时都会调用update方法,并且在调用init方法后的开始时调用。

更新绑定方法用于在viewmodel更改时设置绑定dom元素的状态。

如果您想对更改做出反应并更新viewModel,则需要实现init方法并附加事件(单击,更改等)。在此处理程序中,您可以将状态更新发送到您的viewmodel。

ko.bindingHandlers.statusUpdater = {
    'init': function (element, valueAccessor, allBindingsAccessor) {

        var updateHandler = function() {            
            var valueToWrite;
            if (element.type == "checkbox") {
                valueToWrite = element.checked;
            } else if ((element.type == "radio") && (element.checked)) {
                valueToWrite = element.value;
            } else {
                return; // "checked" binding only responds to checkboxes and selected radio buttons
            }

            var modelValue = valueAccessor();

            if (ko.isWriteableObservable(modelValue)) {             
                if (modelValue() !== valueToWrite) { // Suppress repeated events when there's nothing new to notify (some browsers raise them)
                    $.ajax({
                      url: 'someurl',
                      success: function(data) {
                            alert('status update');
                      }
                    });
                    modelValue(valueToWrite);
                }
            } else {
                var allBindings = allBindingsAccessor();
                if (allBindings['_ko_property_writers'] && allBindings['_ko_property_writers']['checked']) {
                    allBindings['_ko_property_writers']['checked'](valueToWrite);
                }
            }
        };

        $(element).click(updateHandler).change(updateHandler);
    },
    'update': function (element, valueAccessor) {
        ko.bindingHandlers.checked(element, valueAccessor);
    }
};

我发现学习这个的最好方法是在git上查看KO的调试版本。你想要实现的基本上是一个带有ajax调用的修改的检查绑定。

我没有对上述内容进行测试,但它应该让你开始。

干杯,

伊恩