您不能多次将绑定应用于同一元素

时间:2014-01-05 15:15:15

标签: javascript knockout.js

我有一个Bootstrap模式,每次出现时我都会使用KO来绑定<select&gt;下拉列表。

HTML:

<select id="album" name="album" class="form-control" data-bind="options: availableAlbums">
</select>

JavaScript:

$('#uploadModal').on('show.bs.modal', (function () {
        function AlbumsListViewModel() {
            var self = this;
            self.availableAlbums = ko.observableArray([]);

            $.ajax({
                url: "../../api/eventapi/getalbums",
                type: "get",
                contentType: "application/json",
                async: false,
                success: function (data) {
                    var array = [];
                    $.each(data, function (index, value) {
                        array.push(value.Title);
                    });
                    self.availableAlbums(array);
                }
            });
        }

        ko.applyBindings(new AlbumsListViewModel());
    }));

然而,在第二次展示时,KO会向我提出这个错误:

  

错误:您无法多次将绑定应用于同一元素。

1 个答案:

答案 0 :(得分:5)

错误消息说明了大部分内容。您有两种选择:

  1. 在页面加载时调用applyBindings函数一次。当您在AJAX成功函数中更新模型时,KO将自动更新视图。
  2. 在每次AJAX成功时调用applyBIndings函数,但提供其他参数以告诉它要绑定到哪个元素。
  3. 最有可能的第一个选择是你正在寻找的。从$('#uploadModal').on电话中删除电话并将其置于文档加载位置(如果尚未加载)。

    要明白我的意思,这里有两个小提琴:

    1. Your current code您提到的错误。
    2. Refactored version没有错误。
    3. 后者试图尽可能接近你的初始版本(以便专注于手头的问题),并遵循以下几点:

      function AlbumsListViewModel() {
          var self = this;
          self.availableAlbums = ko.observableArray([]);
      }
      
      var mainViewModel = new AlbumsListViewModel();
      ko.applyBindings(mainViewModel);
      
      $('#uploadModal').on('show.bs.modal', (function () {
          // Commenting things out to mock the ajax request (synchronously)
          var data = [{Title:'test'}];
          /*$.ajax({
              url: "../../api/eventapi/getalbums",
              type: "get",
              contentType: "application/json",
              async: false,
              success: function (data) {*/
                  mainViewModel.availableAlbums.removeAll();
                  var array = [];
                  $.each(data, function (index, value) {
                      array.push(value.Title);
                  });
                  mainViewModel.availableAlbums(array);
              /*}
          });*/
      }));