在可观察到的数组更改后,Knockout应用绑定

时间:2016-04-07 05:19:27

标签: javascript knockout.js

我有一个表格,其中包含从挖掘可观察数组中获取的项目,用户输入搜索文本并且巧合填充observableArray,此表格显示在模态上。每个项目都有一个按钮,用于打开另一个具有某些功能的模态(因为不相关而被忽略)。如果observableArray长度大于0,则表必须显示项目,否则,必须显示一行以指示没有结果显示。

<tr style="display: none" data-bind="visible: items().length == 0">
    <td class="text-center alert alert-warning" colspan="4"><b>There's no coincidences</b></td>
</tr>

我的观点模型:

var viewModel = function () {
    self.items= ko.observableArray([]);

    //Modal is already on html, but not visible, to show it I use this
    $('#searchProduct').modal('show');

    //When modal is closed, the table is cleaned, so the items in observableArray are removed
    $('#searchProduct').on('hidden.bs.modal', function () {
        self.items.removeAll();
    });
}

问题是第一次,可见绑定工作正常,但是当observableArray长度发生变化时(隐藏时调用removeAll),不会再次应用绑定。我知道是因为绑定已经应用,所以当observableArray更改时,长度会更新,但条件不能再次呈现html。

如何通过淘汰赛解决这个问题?

(我试图非常具体,但如果需要更多信息,我可以更新信息更清晰)

3 个答案:

答案 0 :(得分:1)

您发布的代码应该可以正常运行。这是一个例子:

function Item() {
  self.txt = ko.observable("Test observable");
}

function RootViewModel() {
  var self = this;
  self.items = ko.observableArray([new Item(), new Item()]);

  $('#searchProduct').modal('show');

  $('#searchProduct').on('hidden.bs.modal', function () {
    self.items.removeAll();
  });
}

ko.applyBindings(new RootViewModel());
pre { background: white; padding: 10px; color: #333; font: 11px consolas; border: 1px solid #ddd; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>

<div id="searchProduct" class="modal fade">
  <div class="modal-dialog">
    <div class="modal-content">Fake Modal</div>
  </div>
</div>

<table>
  <tbody>
    <tr style="display: none" data-bind="visible: items().length == 0">
      <td class="text-center alert alert-warning" colspan="4"><b>There's no coincidences</b>
      </td>
    </tr>
    <!-- ko foreach: items -->
    <tr>
      <td data-bind="text: txt"></td>
    </tr>
    <!-- /ko -->
  </tbody>
</table>

<hr>Debug info: <pre data-bind="text: ko.toJSON($root, null, 2)"></pre>

但请注意,我建议使用a custom binding handler for show/hide of a bs modal,您不应在视图模型中处理DOM交互(如on处理程序)。

答案 1 :(得分:0)

调用removeAll会清空基础数组,并且您的两个observable似乎引用了相同的array.rather而不是调用removeAll,请执行self.items([]);

我创建了一个小提琴示例,用于添加到数组并从数组中删除所有内容。

http://jsfiddle.net/d7mpc6wa/4/

我看不到你的完整HTML代码,所以我在这里创建了一个类似的例子。

<强> HTML

<table>
    <tbody data-bind="foreach: items">
        <tr><td data-bind="text:$data.name"></td></tr>
    </tbody>
    <tbody>
        <tr data-bind="visible: items().length == 0">
            <td class="text-center alert alert-warning" colspan="4"><b>There's no coincidences</b></td>
        </tr>
    </tbody>
</table>

<button data-bind="click:cleanArray">Clean Array</button>
<button data-bind="click:addArray">Add Array</button>

<强>视图模型

   function VM() {
     var self = this;
     var arr = [{name:'name 1'},{name:'name 2'},{name:'name 3'}];     
     self.items = ko.observableArray(arr);
     self.cleanArray = function(){
       self.items([]);
     }

     self.addArray = function(){
       self.items([]);
       self.items(arr);
       console.log(self.items());
     };
   }
  ko.applyBindings(new VM());  

如果有帮助,请告诉我

<强>更新

所以在这里我们可以将数组中的项目移除为self.items([]);self.items.removeAll();,这样就会略有不同。

self.items([]);将用新的空数组替换当前数组。但是self.items.removeAll() 将删除self.items +中的所有项目,它将清空数组实例。

self.array = ['1', '2', '3'];
self.myArray1 = ko.observableArray(self.array);
self.myArray1.removeAll(); 

将清空self.myArray1 +它将清空self.array

以下示例清楚地解释了差异,请看一下。

http://jsfiddle.net/LCQQH/

谢谢

答案 2 :(得分:0)

我很惭愧,我发布的这些代码的一切都很好,错误是当我关闭模式时,我正在删除html中的所有警报类,这显然是在td元素中删除警告警告,所以相反或删除所有警报,什么不是purpouse,我从模态中删除警报危险。我真的很抱歉在SO上发布了这个愚蠢的问题,@ Jeroen,我知道将jQuery与knockout混合来隐藏模态是错误的,只是我不知道如何以正确的方式做到这一点。非常感谢你的回答。