Уверен, что это очень простой вопрос для ответа, но есть ли простой способ определить, изменилось ли какое-либо свойство модели нокаута?
Обнаружение изменений в модели представления нокаутов
Ответ 1
Используйте удлинители:
ko.extenders.trackChange = function (target, track) {
if (track) {
target.isDirty = ko.observable(false);
target.originalValue = target();
target.setOriginalValue = function(startingValue) {
target.originalValue = startingValue;
};
target.subscribe(function (newValue) {
// use != not !== so numbers will equate naturally
target.isDirty(newValue != target.originalValue);
});
}
return target;
};
Тогда:
self.MyProperty= ko.observable("Property Value").extend({ trackChange: true });
Теперь вы можете проверить следующее:
self.MyProperty.isDirty()
Вы также можете написать общий ролик просмотраModel, чтобы увидеть, что-то изменилось:
self.isDirty = ko.computed(function () {
for (key in self) {
if (self.hasOwnProperty(key) && ko.isObservable(self[key]) && typeof self[key].isDirty === 'function' && self[key].isDirty()) {
return true;
}
}
});
... а затем просто проверьте на уровне уровня представления
self.isDirty()
Ответ 2
Вы можете подписаться на свойства, которые вы хотите отслеживать:
myViewModel.personName.subscribe(function(newValue) {
alert("The person new name is " + newValue);
});
Это будет отображаться при изменении имени пользователя.
Хорошо, поэтому вы хотите знать, когда что-то изменится в вашей модели...
var viewModel = … // define your viewModel
var changeLog = new Array();
function catchChanges(property, value){
changeLog.push({property: property, value: value});
viewModel.isDirty = true;
}
function initialiseViewModel()
{
// loop through all the properties in the model
for (var property in viewModel) {
if (viewModel.hasOwnProperty(property)) {
// if they're observable
if(viewModel[property].subscribe){
// subscribe to changes
viewModel[property].subscribe(function(value) {
catchChanges(property, value);
});
}
}
}
viewModel.isDirty = false;
}
function resetViewModel() {
changeLog = new Array();
viewModel.isDirty = false;
}
(не тестировал его, но вы должны получить идею)
Ответ 3
Рассмотрим использование плагин для проверки нокаута
Он реализует следующее:
yourProperty.isModified() - проверяет, изменил ли пользователь значение.
yourProperty.originalValue - Таким образом, вы можете проверить, действительно ли значение изменилось.
Наряду с другими материалами проверки, которые вам пригодится!
Приветствия
Ответ 4
Вы можете использовать плагин ниже для этого:
https://github.com/ZiadJ/knockoutjs-reactor
Код, например, позволит вам отслеживать все изменения в любом представленииModel:
ko.watch(someViewModel, { depth: -1 }, function(parents, child) {
alert('New value is: ' + child());
});
PS: На данный момент это не будет работать с подписчиками, вложенными в массив, но новая версия, которая его поддерживает, находится в пути.
Обновление:. Пример кода был обновлен для работы с v1.2b, который добавляет поддержку элементов массива и свойств, доступных для подписки.
Ответ 5
У меня была такая же проблема, мне нужно было наблюдать любые изменения в viewModel, чтобы отправить данные обратно на сервер, Если кто-то все еще интересовался, я провел некоторое исследование, и это лучшее решение, которое удалось собрать:
function GlobalObserver(viewModel, callback) {
var self = this;
viewModel.allChangesObserver = ko.computed(function() {
self.viewModelRaw = ko.mapping.toJS(viewModel);
});
viewModel.allChangesObserver.subscribe(function() {
callback(self.viewModelRaw);
});
self.dispose = function() {
if (viewModel.allChangesObserver)
viewModel.allChangesObserver.dispose();
delete viewModel.allChangesObserver;
};
};
чтобы использовать этот "глобальный наблюдатель":
function updateEntireViewModel() {
var rawViewModel = Ajax_GetItemEntity(); //fetch the json object..
//enter validation code here, to ensure entity is correct.
if (koGlobalObserver)
koGlobalObserver.dispose(); //If already observing the older ViewModel, stop doing that!
var viewModel = ko.mapping.fromJS(rawViewModel);
koGlobalObserver = new GlobalObserver(viewModel, Ajax_Submit);
ko.applyBindings(viewModel [ ,optional dom element]);
}
Обратите внимание, что указанный обратный вызов (в данном случае "Ajax_Submit" ) запускается при ЛЮБЫХ изменениях, которые происходят в модели представления, поэтому я считаю, что действительно рекомендуется сделать какой-то механизм задержки для отправки объекта только тогда, когда пользователь для редактирования свойств:
var _entitiesUpdateTimers = {};
function Ajax_Submit(entity) {
var key = entity.ID; //or whatever uniquely related to the current view model..
if (typeof _entitiesUpdateTimers[key] !== 'undefined')
clearTimeout(_entitiesUpdateTimers[key]);
_entitiesUpdateTimers[key] =
setTimeout(function() { SendEntityFunction(entity); }, 500);
}
Я новичок в JavaScript и фреймворке нокаута, (только yestarday начал работать с этой замечательной рамкой), поэтому не сердитесь на меня, если я сделал что-то не так.. (-:
Надеюсь, это поможет!
Ответ 6
Я адаптировал код @Brett Green и расширил его, чтобы мы могли иметь AcceptChanges, отмечая модель как не грязную, а также более удобный способ маркировки моделей в качестве треков. Вот код:
var viewModel = {
name: ko.observable()
};
ko.track(viewModel);
Ответ 7
Я сделал это, сделав снимок модели представления при загрузке страницы, а затем позже сравнив этот снимок с текущей моделью просмотра. Мне все равно, какие свойства изменились, только если они изменились.
Сделайте снимок:
var originalViewModel = JSON.stringify(ko.toJS(viewModel));
Сравнить позже:
if(originalViewModel != JSON.stringify(ko.toJS(viewModel))){
// Something has changed, but we don't know what
}
Ответ 8
Рассмотрим модель представления следующим образом
function myViewModel(){
var that = this;
that.Name = ko.observable();
that.OldState = ko.observable();
that.NewState = ko.observable();
that.dirtyCalcultions - ko.computed(function(){
// Code to execute when state of an observable changes.
});
}
После привязки данных вы можете сохранить состояние с помощью функции ko.toJS(myViewModel).
myViewModel.Name("test");
myViewModel.OldState(ko.toJS(myViewModel));
Вы можете объявить переменную внутри вашей модели представления в виде вычисленного наблюдаемого типа
that.dirtyCalculations = ko.computed(function () {});
Эта вычисленная функция будет введена при изменении любого из других наблюдаемых в модели представления.
Затем вы можете сравнить два состояния модели представления как:
that.dirtyCalculations = ko.computed(function () {
that.NewState(that);
//Compare old state to new state
if(that.OldState().Name == that.NewState().Name()){
// View model states are same.
}
else{
// View model states are different.
}
});
** Примечание. Эта вычисленная наблюдаемая функция также выполняется при первом инициализации модели представления. **
Надеюсь, это поможет! Ура!!