我一直在尝试订阅下拉列值更改时的订阅。我有以下逻辑,但我似乎无法使其正常工作。
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);
}
});
}
下拉列表中的实际值都会更改以匹配从服务器返回的值,但是每当我手动更改下拉列表时,都不会触发订阅事件。
答案 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
。