From 2a295779d77e94300e7aea6a4072c638179fc888 Mon Sep 17 00:00:00 2001 From: Ignacio Baixas Date: Wed, 10 Dec 2014 23:18:07 -0300 Subject: [PATCH] feat(plugin.nested_dirty): specifies how changing a nested object property to another type affects changed property list. --- src/plugins/nested-dirty.js | 25 ++++++++++++------------- test/plugins/nested-dirty-spec.js | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/plugins/nested-dirty.js b/src/plugins/nested-dirty.js index becdd0f..b5fae6a 100644 --- a/src/plugins/nested-dirty.js +++ b/src/plugins/nested-dirty.js @@ -29,27 +29,28 @@ angular.module('restmod').factory('NestedDirtyModel', ['restmod', function(restm function navigate(_target, _keys) { var key, i = 0; while((key = _keys[i++])) { - if(_target && _target.hasOwnProperty(key)) _target = _target[key]; + if(_target) { + _target = _target.hasOwnProperty(key) ? _target[key] : null; + } } return _target; } function hasValueChanged(_model, _original, _keys, _comparator) { - var isDirty = false, - prop = _keys.pop(); + var prop = _keys.pop(); _model = navigate(_model, _keys); _original = navigate(_original, _keys); - if(_original.hasOwnProperty(prop)) { + if(angular.isObject(_original) && angular.isObject(_model) && _original.hasOwnProperty(prop)) { if(typeof _comparator === 'function') { - isDirty = !!_comparator(_model[prop], _original[prop]); + return !!_comparator(_model[prop], _original[prop]); } else { - isDirty = !angular.equals(_model[prop], _original[prop]); + return !angular.equals(_model[prop], _original[prop]); } } - return isDirty; + return false; } function findChangedValues(_model, _original, _keys, _comparator) { @@ -61,10 +62,8 @@ angular.module('restmod').factory('NestedDirtyModel', ['restmod', function(restm if(isPlainObject(_original[key]) && isPlainObject(_model[key])) { childChanges = findChangedValues(_model[key], _original[key], _keys.concat([key]), _comparator); changes.push.apply(changes, childChanges); - } else { - if(hasValueChanged(_model, _original, [key], _comparator)) { - changes.push(_keys.concat([key])); - } + } else if(hasValueChanged(_model, _original, [key], _comparator)) { + changes.push(_keys.concat([key])); } } } @@ -73,7 +72,7 @@ angular.module('restmod').factory('NestedDirtyModel', ['restmod', function(restm return changes; } - function changesToStrings(_changes) { + function changesAsStrings(_changes) { for(var i = 0, l = _changes.length; i < l; i++) { _changes[i] = _changes[i].join('.'); } @@ -123,7 +122,7 @@ angular.module('restmod').factory('NestedDirtyModel', ['restmod', function(restm return hasValueChanged(this, original, _prop.split('.'), _comparator); } else { if(angular.isFunction(_prop)) _comparator = _prop; - return changesToStrings(findChangedValues(this, original, [], _comparator)); + return changesAsStrings(findChangedValues(this, original, [], _comparator)); } }) /** diff --git a/test/plugins/nested-dirty-spec.js b/test/plugins/nested-dirty-spec.js index ed749d7..62bcbe4 100644 --- a/test/plugins/nested-dirty-spec.js +++ b/test/plugins/nested-dirty-spec.js @@ -47,11 +47,24 @@ describe('Plugin: Nested Dirty Model', function() { expect(bike.$dirty()).toContain('stickers'); }); - it('should detect missing objects', function() { + it('should detect missing object properties', function() { bike.customisations = null; expect(bike.$dirty()).toContain('customisations'); }); + it('should detect properties that change type from object', function() { + bike.customisations = 0; + expect(bike.$dirty()).toContain('customisations'); + }); + + it('should not consider changes on child properties when parent object changes', function() { + bike.customisations = null; + expect(bike.$dirty('customisations.wheels')).toBeFalsy(); + + bike.model = { name: 'Meta', version: '2' }; + expect(bike.$dirty('model.name')).toBeFalsy(); + }); + it('should compare with comparator function', function() { bike.customisations.wheels = 3; expect(bike.$dirty('customisations.wheels', function (newVal, oldVal) {