Knockoutjs中的BindingHandler。构建自己的ListView

时间:2012-06-14 11:03:07

标签: jquery knockout.js

我想用selectedItem和Itemsource构建我自己的listView。

我已经开始使用jsFiddle http://jsfiddle.net/andersb79/53xRL/1/

请你帮我指明如何建立这个方向。 我没有见过这样做的具有约束力的汉德尔。

我想要的是这样的。

data-bind="myListView : { items : comments, selectedItem : selectedComment}"

1 个答案:

答案 0 :(得分:1)

在您的自定义绑定中,您需要:

  1. 为列表中的每个项目创建一个元素
  2. 将该元素附加到父
  3. 为在原始视图模型上设置selectedItem的每个元素添加一个单击处理程序
  4. 为了清晰起见,我还突出显示了当前所选项目。

    ko.bindingHandlers.myListView = {
        update: function(element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor()),
    
                //get the list of items
                items = value.items(),
                //get a reference to the selected item observable
                selectedItem = value.selectedItem,
                //get a jQuery reference to the element
                $element = $(element),
                //get the currently selected item
                currentSelected = selectedItem();
    
            //clear the parent of any existing children
            $element.html("");
    
            for (var index = 0; index < items.length; index++) {
                (function() {
                    //get the list of items
                    var item = ko.utils.unwrapObservable(items[index]),
    
                        //create a child element with a click handler
                        $childElement = $("<li>")
                        .text(item.id() + " " + item.text())
                        .click(function() {
                            //remove selected class on all siblings
                            $(this).siblings().removeClass("selected");
                            //add selected class on this item
                            $(this).addClass("selected");
                            //set the observable 'selected item' property on the source view model
                            selectedItem(item);
                        });
    
                    //add the selected class if this item is the current selected item
                    if (item == currentSelected) {
                        $childElement.addClass("selected");
                    }
    
                    //add the child to the parent
                    $element.append($childElement);
                })();
            }
    
        }
    };
    

    这是working example

    注意:当我使用update代替init方法时,它会在更新评论列表时起作用

    <强>更新

    如果要将原始DIV的内容用作每个已创建项目的模板,则需要执行两个步骤:

    1. 初始化时抓取元素的原始内容,并使用它代替上面的硬编码内容
    2. 在将创建的元素添加到DOM

      之前将其应用于创建的元素
          ko.bindingHandlers.myListView = {
      init: function(element) {
          var $element = $(element),
              originalContent = $element.html();
      
          $element.data("original-content", originalContent);
          return { controlsDescendantBindings: true }
      },
      update: function(element, valueAccessor) {
          var value = ko.utils.unwrapObservable(valueAccessor()),
      
              //get the list of items
              items = value.items(),
              //get a reference to the selected item observable
              selectedItem = value.selectedItem,
              //get a jQuery reference to the element
              $element = $(element),
              //get the currently selected item
              currentSelected = selectedItem(),
              //get the current content of the element
              elementContent = $element.data("original-content");
      
          $element.html("");
      
          for (var index = 0; index < items.length; index++) {
              (function() {
                  //get the list of items
                  var item = ko.utils.unwrapObservable(items[index]),
      
                      //create a child element with a click handler
                      $childElement = $(elementContent)
                      .click(function() {
                          //remove selected class on all siblings
                          $(this).siblings().removeClass("selected");
                          //add selected class on this item
                          $(this).addClass("selected");
                          //set the observable 'selected item' property on the source view model
                          selectedItem(item);
                      });
      
                  ko.applyBindings(item, $childElement[0]);
      
                  //add the selected class if this item is the current selected item
                  if (item == currentSelected) {
                      $childElement.addClass("selected");
                  }
      
                  //add the child to the parent
                  $element.append($childElement);
              })();
          }
      
      }
      

      };

    3. 请注意,我们必须通过从{ controlsDescendantBindings: true }方法返回init来阻止正在淘汰div的内容。

      这是updated example