淘汰订阅不起作用

时间:2016-08-09 11:05:09

标签: javascript knockout.js

我一直在尝试订阅下拉列值更改时的订阅。我有以下逻辑,但我似乎无法使其正常工作。

HTML

            <div id="case-pin-@modelItem.CaseID" data-caseid="@modelItem.CaseID" class="row hidden popovercontainer pinBinding">
                <select data-bind="options:userPins,
                        value:selectedPin,
                        optionsCaption:'-- please select --',
                        optionsText: 'Name',
                        optionsValue: 'Id'"></select>
            </div>

JS

function UserPinViewModel(caseId) {
    var self = this;
    self.selectedPin = ko.observable();
    self.userPins = ko.observableArray([]);
    self.caseId = caseId;

    self.selectedPin.subscribe(function (newValue) {
        console.log(newValue);
        //addCaseToPin(newValue, self.caseId);
    });
}

var pinObjs = [];

$(function () {
    pinObjs = [];

    $(".pinBinding").each(function () {
        var caseId = this.getAttribute("data-caseid");
        var view = new UserPinViewModel(caseId);
        pinObjs.push(view);

        ko.cleanNode(this);
        ko.applyBindings(view, this);
    });
})

userPins数组由对服务器的AJAX调用填充,因为下拉列表中的值取决于网站的另一部分,它可以更改下拉列表中的值 - 这是我用来填充数组的逻辑。 / p>

function getPins() {
    $.ajax({
        type: 'POST',
        url: '/Home/GetPins',
        success: function (data) {
                for (var i = 0; i < pinObjs.length; i++) {
                    pinObjs[i].userPins(data);
                }
        },
        error: function (request, status, error) {
            alert("Oooopppppsss! Something went wrong - " + error);
        }
    });
}

下拉列表中的实际值都会更改以匹配从服务器返回的值,但是每当我手动更改下拉列表时,都不会触发订阅事件。

1 个答案:

答案 0 :(得分:0)

你正在使用jQuery和Knockout来操纵DOM,这不是一个好主意。 Knockout的整个想法是你不操纵DOM,它确实如此。你操纵你的viewModel。

使用cleanNode也是一种代码气味,表明你做错了事。如果您使用Knockout提供的工具,Knockout将处理该问题。

在这种情况下,我打算建议一个自定义绑定处理程序,但看起来你真正想要的是创建一个UserPinViewModel对象并将其应用于.pinBinding元素的每个实例。 HTML。如果在viewModel中公开UserPinViewModel构造函数,则可以使用with binding执行此操作。

function UserPinViewModel(caseId) {
  var self = this;
  self.selectedPin = ko.observable();
  self.userPins = ko.observableArray([]);
  self.caseId = caseId;

  self.selectedPin.subscribe(function(newValue) {
    console.log(newValue);
    //addCaseToPin(newValue, self.caseId);
  });

  // Pretend Ajax call to set pins
  setTimeout(() => {
    self.userPins([{
      Name: 'option1',
      Id: 1
    }, {
      Name: 'option2',
      Id: 2
    }, {
      Name: 'option3',
      Id: 3
    }])
  }, 800);

  // Later, the options change
  setTimeout(() => {
    self.userPins([{
      Name: 'animal1',
      Id: 'Elephant'
    }, {
      Name: 'animal2',
      Id: 'Pony'
    }, {
      Name: 'animal3',
      Id: 'Donkey'
    }])
  }, 4000);

}

ko.bindingHandlers.pin = {
  init: () => null,
  update: () => null
};

ko.applyBindings({
  pinVm: UserPinViewModel
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div id="case-pin-@modelItem.CaseID" data-bind="with: new pinVm('someCaseId')" class="row hidden popovercontainer pinBinding">
  <select data-bind="options:userPins,
                     value:selectedPin,
                     optionsCaption:'-- please select --',
                     optionsText: 'Name',
                     optionsValue: 'Id'"></select>
</div>

您的getPins函数表明.pinBinding元素应与接收的数据相对应。在这种情况下,pinObjs应该是viewModel的一部分,并且应该从数据生成元素(可能在foreach中),而不是硬编码。我不知道如何使用我认为的服务器端@modelItem.CaseID