订阅事件在设置值时被调用

时间:2014-10-22 13:49:39

标签: html knockout.js observable

我在html绑定到可观察数组

中选择了列表
 <select data-bind="options: myData, optionsText: 'Name', value: selectedId"></select>

当我加载页面时,我将值设置为可观察的selectedId

但是当我设置值时,它会立即调用其订阅事件

  selectedId.subscribe(function (row) {
      // some logic for retrieving data
  });

我不希望订阅事件在以编程方式设置值时调用,但只想在用户从列表中选择内容时调用。

有可能吗?无法找到任何好的例子。

UPDATE1 我以这种方式将值设置为我的可观察selectedId

selectedId(ko.utils.arrayFirst(data(), function(item) {
                    return item.id=== 5;
}));

我认为因为它的触发订阅事件

1 个答案:

答案 0 :(得分:1)

如果您在实际订阅之前设置了初始值,那么您不应该获得订阅事件。例如:

function ViewModel() {
  var self = this;

  self.selectedID = ko.observable();
  self.selectedID(10); // this won't fire the event because we haven't subscribed yet

  self.selectedID.subscribe(function(value) {
    alert("value changed by user");
  });
}

ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input type="number" data-bind="value: selectedID" />

现在,如果你想解决一般情况,那么值可能会在以后以编程方式更改,而你不希望subscribe触发,那么你可能想要一个可以用来简单跳过的标志处理subscribe处理程序。类似的东西:

function ViewModel() {
  var self = this;

  self.selectedID = ko.observable();
  self.selectedID(10); // this won't fire the event because we haven't subscribed yet

  var _skipNotification = false; // this tells us whether or not we should process subscribe

  // putting this logic in a function makes it easier if you have multiple places 
  // where you need to programmatically set the id.
  function setSelectedID(value) {
    _skipNotification = true;
    self.selectedID(value);
    _skipNotification = false;
  }

  self.selectedID.subscribe(function(value) {
    if (!_skipNotification) {
      alert("value changed by user");
    }
  });

  self.changeProgrammatically = function() {
    setSelectedID(1);
  };
}

ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input type="number" data-bind="value: selectedID" />
<input type="button" data-bind="click: changeProgrammatically" value="change programmatically" />

这是你的fiddle修复使用上述技术。局部变量_skipNotification在视图模型中定义,并在subscribe事件中进行检查。然后,从鼠标单击调用的importData函数如下所示:

 this.importData = function () {
     skipNotification = true;
     self.selectedGroup(ko.utils.arrayFirst(self.availableGroups(), function (val) {
         //debugger;
         return val.GroupId == 8;
     }));
     skipNotification = false;

     console.log("Lets see if it hits me first");
 };

这将设置selectedGroup而不会导致selectedGroup.subscribe的正文执行。请注意,因此selectedGroupId未设置,因此尽管在下拉列表中选择了某些内容,但您的一个范围仍会显示You have chosen Nothing。我不确定这是不是你真正想要的,但它似乎很有误导性。特别是因为现在让它正确阅读You have chosen Football Team的唯一方法是首先选择其他内容,然后重新选择Football Team