How to cancel/revert changes to an observable model (or replace model in array with untouched copy)

前端 未结 5 1963
萌比男神i
萌比男神i 2021-01-01 12:19

I have a viewModel with an observableArray of objects with observable variables.

My template shows the data with an edit button that hides the display elements and s

5条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-01-01 12:29

    I needed something similar, and I couldn't use the protected observables, as I needed the computed to update on the temporary values. So I wrote this knockout extension:

    This extension creates an underscore version of each observable ie self.Comments() -> self._Comments()

    ko.Underscore = function (data) {
        var obj = data;
        var result = {};
        // Underscore Property Check
        var _isOwnProperty = function (isUnderscore, prop) {
            return (isUnderscore == null || prop.startsWith('_') == isUnderscore) && typeof obj[prop] == 'function' && obj.hasOwnProperty(prop) && ko.isObservable(obj[prop]) && !ko.isComputed(obj[prop])
        }
        // Creation of Underscore Properties
        result.init = function () {
            for (var prop in obj) {
                if (_isOwnProperty(null, prop)) {
                    var val = obj[prop]();
                    var temp = '_' + prop;
                    if (obj[prop].isObservableArray)
                        obj[temp] = ko.observableArray(val);
                    else
                        obj[temp] = ko.observable(val);
                }
            }
        };
        // Cancel
        result.Cancel = function () {
            for (var prop in obj) {
                if (_isOwnProperty(false, prop)) {
                    var val = obj[prop]();
                    var p = '_' + prop;
                    obj[p](val);
                }
            }
        }
        // Confirm
        result.Confirm = function () {
            for (var prop in obj) {
                if (_isOwnProperty(true, prop)) {
                    var val = obj[prop]();
                    var p = prop.replace('_', '');
                    obj[p](val);
                }
            }
        }
        // Observables
        result.Properties = function () {
            var obs = [];
            for (var prop in obj) {
                if (typeof obj[prop] == 'function' && obj.hasOwnProperty(prop) && ko.isObservable(obj[prop]) && !ko.isComputed(obj[prop])) {
                    var val = obj[prop]();
                    obs.push({ 'Name': prop, 'Value': val });
                }
            }
            return obs;
        }
    
        if (obj != null)
            result.init();
    
        return result;
    }
    

    This extension will save you writing duplicates of each of your observables and ignores your computed. It works like this:

    var BF_BCS = function (data) {
        var self = this;
    
        self.Score = ko.observable(null);
        self.Comments = ko.observable('');
    
        self.Underscore = ko.Underscore(self);
    
        self.new = function () {
            self._Score(null);
            self._Comments('');
            self.Confirm();
        }
    
        self.Cancel = function () {
            self.Pause();
            self.Underscore.Cancel();
            self.Resume();
        }
    
        self.Confirm = function () {
            self.Pause();
            self.Underscore.Confirm();
            self.Resume();
        }
    
        self.Pause = function () {
    
        }
    
        self.Resume = function () {
    
        }
    
        self.setData = function (data) {
            self.Pause();
    
            self._Score(data.Score);
            self._Comments(data.Comments);
            self.Confirm();
            self.Resume();
        }
    
        if (data != null)
            self.setData(data);
        else
            self.new();
    };
    

    So as you can see if you have buttons on html:

    
    

    Cancel will undo and revert your observables back to what they were, as were save will update the real values with the temp values in one line

提交回复
热议问题