Knockout js: загрузить модель из JSON
У меня проблема с моей моделью. Я пытаюсь загрузить модель из JSON, но она не работает должным образом:(Я создал каскадные списки выбора. Когда я пытаюсь сохранить модель в JSON и после этого загрузить ее из сохраненного JSON, это вызывает неправильные значения выбора списки.
Вот моя привязка:
<div id="condition-template" type="text/html">
<div class="condition">
<select class="textbox1"
data-bind="options: entarea,
optionsText : 'displayName',
value: selectedArea " ></select>
<select class="textbox1"
data-bind="options: Selectedfields,
optionsText : 'fieldDisplayName',
value: selectedField "></select>
<select class="textbox1"
data-bind="options: Selectedcomparisons,
optionsText : 'comparsionDisplayName',
value: selectedComparison "></select>
<input class="textbox1" type="text" data-bind="value: value"></input>
<button data-bind='click: save'>Save to JSON</button>
<button data-bind='click: loadModel'>AddModel</button>
</p>
<textarea data-bind='value: lastSavedJson' rows='5' cols='60' > </textarea>
<inner type = "textarea" id="t_test"></inner>
</div>
</div>
Моя модель:
function Condition() {
var self = this;
var sqlArea = function(sqlAreaId, displayName) {
this.displayName = ko.observable(displayName);
this.sqlAreaId = ko.observable(sqlAreaId);
};
var field = function(fieldId, fieldDisplayName, sqlAreaId, fieldType) {
this.fieldId = ko.observable(fieldId);
this.fieldDisplayName = ko.observable(fieldDisplayName);
this.sqlAreaId = ko.observable(sqlAreaId);
this.fieldType = ko.observable(fieldType);
};
var comparison = function(comparsionId, comparsionDisplayName, fieldType) {
this.comparsionId = ko.observable(comparsionId);
this.comparsionDisplayName = ko.observable(comparsionDisplayName);
this.fieldType = ko.observable(fieldType);
};
self.templateName = "condition-template";
self.entarea = ko.observableArray([new sqlArea(1, "Client"),
new sqlArea(2, "Order")]);
self.selectedArea = ko.observable();
self.fields = ko.observableArray([new field( 1, "Name", 1, 1),
new field( 2, "Address", 1, 1),
new field( 3, "Phone number", 1, 1),
new field( 4, "Manager", 1, 1),
new field( 5, "Type", 1, 2),
new field( 6, "Order number", 2, 2),
new field( 7, "Sum", 2, 2),
new field( 8, "Date", 2, 3)]);
self.selectedField = ko.observable();
self.comparisons = ko.observableArray([new comparison( 1,">=", 2),
new comparison( 2,">", 2),
new comparison( 3,"<=", 3),
new comparison( 4,"IN from date", 3),
new comparison( 5,"IN from string", 1)
]);
self.selectedComparison = ko.observable();
//------------------------------------------------------------------------
//Cascading select list
self.Selectedfields = ko.dependentObservable(function () {
var area = self.selectedArea(), sqlAreaId;
if (area) {
sqlAreaId = area.sqlAreaId();
return ko.utils.arrayFilter(self.fields(), function(field) {
return field.sqlAreaId() === sqlAreaId;
});
}
return [];
}, self);
self.Selectedcomparisons = ko.dependentObservable(function() {
var field = self.selectedField(), fieldType;
if (field) {
fieldType = field.fieldType();
return ko.utils.arrayFilter(self.comparisons(),function(comparison) {
return comparison.fieldType() === fieldType;
});
}
return [];
}, self);
//-----------------------------------------------------------------------
self.value = ko.observable(0);
self.save = function() {
self.lastSavedJson(JSON.stringify( ko.mapping.toJS(self), null, 2));
var test = document.getElementById('t_test');
test.innerHTML = (JSON.stringify( ko.mapping.toJS(self), null, 2));
};
self.lastSavedJson = ko.observable("");
self.loadModel = function() {
var test = document.getElementById('t_test');
var data = JSON.parse(test.innerHTML);
ko.mapping.fromJS(data, {}, self);
/* var viewModel = {};
viewModel.model = ko.mapping.fromJS(data, {}, self);
self.updateFromModel(self, viewModel.model);*/
};
}
ko.applyBindings(new Condition());
ОБНОВЛЕНИЕ 1: http://jsfiddle.net/3EWVR/2/
Например, когда я выбираю order/sum/>=/8 и сохраняю его в JSON, я выбираю другие значения (например, client / address / in из строки / 0) и загружаю сохраненные модели данных из JSON, я ожидаю получить оригинал вход (order/sum/>=/8), но в элементе выбора нет никаких значений, и он дублирует значения в списке выбора.
1 ответ
Я полагаю, что корень проблемы заключается в некотором разделении ссылок на объекты. Примите к сведению различные сценарии, изображенные в этой скрипке.
Однако это базовое объяснение требует дальнейшего разъяснения, поскольку
Order
Модели вызовут дублирование в течение первого<select>
в то время какClient
моделей нет. Оба типа также вызовут дублирование во втором<select>
,Указанный индекс всегда равен [0], что объясняет, почему
Client
не дублирует Затронутый индекс0
часть я еще не совсем понял.
По причинам, которые мне еще предстоит расследовать, указав update callback
ko.mapping.fromJS( init, {
'selectedArea': {
update: function (options) {
return options.data;
}
}
}, new Condition())
в пределах карты options
параметры, кажется, смягчают проблему.
Альтернативой было бы ввести
optionsValue
привязка и поиск объектов при необходимости с помощью функции ko.utilsредактировать
После более пристального взгляда на применение options
в фактическом источнике против моего уменьшенного примера у меня все еще были некоторые проблемы со ссылками на объекты. Поэтому я применил свой альтернативный подход.
<select>
элементы теперь используют optionsValue
обязательный параметр. Единственное место, где это влияет на источник, находится в Selectedcomparisons
, Вы должны найти поле для доступа к fieldType
имущество.
var selectedField = ko.utils.arrayFirst(self.Selectedfields(), function (field) {
return field.fieldId() === self.selectedField();
});
Другие соображения
Вы разбирали
JSON
а потомko.mapping.fromJS
на этом я изменил этоko.mapping.fromJSON(self.lastSavedJson(), options, self)
dependentObservables
не может быть записано как определено, поэтому я пометил их как проигнорированныеvar options = {ignore: []} var propertyNames = Object.keys(self); for(index in propertyNames){ var property = propertyNames[index] if(ko.isComputed(self[property])){ options.ignore.push(property) } };