Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a dirty flag or undo stack with Knockout.js and Knockout.mapping.js

I am trying to create or use an existing dirtyFlag. However all the examples I've seen don't talk about how to integrate them with knockout.mapping.js plugin.

There are a lot of really great examples out there like Ryan Niemeyer's stuff and John Papa's KoLite, but they all fail to answer the simple question of

"I've got a lot of properties on my viewModel and I don't have time for hand coding something that should be handled by the knockout mapping plugin"

I feel like this is a dirty (no pun intended) little secret that needs to get out.

Thanks!

like image 354
Mr. Young Avatar asked Jan 30 '26 17:01

Mr. Young


1 Answers

I'm no expert on the knockout library but i'm a big fan of simple solutions. John Papa and Hans Fjallemarks solution in KoLite: https://github.com/CodeSeven/kolite is an excellent solution for a simple but most effective dirty flag on all or selected observables in a viewmodel.

I've done a little tweaking to it to include undo.

ko.DirtyFlag = function (objectToTrack, isInitiallyDirty, hashFunction) {

    hashFunction = hashFunction || ko.toJSON;

    var
        self = this,
        _objectToTrack = objectToTrack,
        _lastCleanState = ko.observable(hashFunction(_objectToTrack)),
        _isInitiallyDirty = ko.observable(isInitiallyDirty),

        result = function () {
            self.forceDirty = function () {
                _isInitiallyDirty(true);
            };

            self.isDirty = ko.computed(function () {
                return _isInitiallyDirty() || hashFunction(_objectToTrack) !== _lastCleanState();
            });

            self.reset = function () {
                _lastCleanState(hashFunction(_objectToTrack));
                _isInitiallyDirty(false);
            };

            self.undo = function () {
                var source = JSON.parse(_lastCleanState());
                for (prop in source) {
                    if (_objectToTrack[prop]() && _objectToTrack[prop]() != source[prop]) {
                        _objectToTrack[prop](source[prop]);
                    }
                }
                _isInitiallyDirty(false);
            };
            return self;
        };

    return result;
};
like image 50
Jan R Avatar answered Feb 02 '26 16:02

Jan R



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!