Обновление обработчиков связывания нокаута не запускается для изменений наблюдаемого массива
Я пытаюсь получить доступ к нескольким значениям через один обработчик связывания, в случае изменений observableArray, которые находятся внутри объекта привязки valuesAccessor, обновление обработчика связывания не запускается.
ko.bindingHandlers.chosen = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
console.log("INIT");
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var value = ko.unwrap(valueAccessor());
ko.utils.arrayForEach(value,function(binding){
var value = ko.unwrap(binding);
});
console.log("IT WORKS!");
}
};
<select data-bind="
options: Options,
chosen: {options: Options}
"></select>
Демо: ( также на jsFiddle):
ko.bindingHandlers.chosen = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
console.log("INIT");
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var value = ko.unwrap(valueAccessor());
ko.utils.arrayForEach(value,function(binding){
var value = ko.unwrap(binding);
});
console.log("IT WORKS!");
}
};
function Model() {
this.Options = ko.observableArray(opt1);
this.Reload = function () {
if (!this.index) {
this.Options(opt2);
this.index = 1;
} else {
this.Options(opt1);
this.index = 0;
}
this.Options.valueHasMutated();
};
this.index = 0;
}
var opt1 = [{
Text: "1",
Value: "1"
}, {
Text: "2",
Value: "2"
}, ];
var opt2 = [{
Text: "3",
Value: "3"
}, {
Text: "4",
Value: "4"
}, ];
ko.applyBindings(new Model());
<select data-bind="
options: Options,
value: Selection,
optionsText: 'Text',
optionsValue: 'Value',
chosen: {options: Options}
"></select>
<input type="button" data-bind="click: Reload" value="reload" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
1 ответ
Проблема в том, что ваш chosen
привязка на самом деле не обращается к наблюдаемому массиву, поэтому при его изменении нокаут не вызывает ваш update
обработчик, потому что он не думает, что что-то изменилось, что он использует.
С этой привязкой:
chosen: {options: Options}
Вы связываете совершенно новый объект (с options
свойство, указывающее на ваш Options
наблюдаемый массив). Это означает, что когда вы делаете
var value = ko.unwrap(valueAccessor());
value
теперь содержит: {options: <observableArrayFunction>}
- вам нужно получить доступ к options
Свойство на него для нокаута зарегистрировать по ссылке:
ko.utils.arrayForEach(value.options(),function(binding){
});
Если вы сделаете это изменение, вы увидите, что "IT WORKS!"
теперь регистрируется при обновлении. На самом деле он регистрируется дважды, один раз, потому что вы обновляете массив, и другой, потому что вы звоните valueHasMutated
,
Обновленный фрагмент (с дополнительным valueHasMutated
удалены):
ko.bindingHandlers.chosen = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
console.log("INIT");
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var value = ko.unwrap(valueAccessor());
ko.utils.arrayForEach(value.options(),function(binding){
var value = ko.unwrap(binding);
});
console.log("IT WORKS!");
}
};
function Model() {
this.Options = ko.observableArray(opt1);
this.Reload = function () {
if (!this.index) {
this.Options(opt2);
this.index = 1;
} else {
this.Options(opt1);
this.index = 0;
}
};
this.index = 0;
}
var opt1 = [{
Text: "1",
Value: "1"
}, {
Text: "2",
Value: "2"
}, ];
var opt2 = [{
Text: "3",
Value: "3"
}, {
Text: "4",
Value: "4"
}, ];
ko.applyBindings(new Model());
<select data-bind="
options: Options,
value: Selection,
optionsText: 'Text',
optionsValue: 'Value',
chosen: {options: Options}
"></select>
<input type="button" data-bind="click: Reload" value="reload" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>