diff --git a/src/directives/sf-array.directive.js b/src/directives/sf-array.directive.js index cee5fe3d4..21e416dde 100644 --- a/src/directives/sf-array.directive.js +++ b/src/directives/sf-array.directive.js @@ -186,10 +186,6 @@ export default function(sfSelect, sfPath, schemaForm) { model.splice(index, 1); } - if(item.$$hashKey) { - scope.destroyed = item.$$hashKey; - } - return model; }; diff --git a/src/directives/sf-array.directive.spec.js b/src/directives/sf-array.directive.spec.js index bd9ac27d5..5c91a805d 100644 --- a/src/directives/sf-array.directive.spec.js +++ b/src/directives/sf-array.directive.spec.js @@ -24,9 +24,14 @@ describe('sf-array.directive.js', function() { "type": "array", "description": "foobar", "items": { - "title": "Name", - "type": "string", - "default": 6, + "type": "object", + "properties": { + "name": { + "title": "Name", + "type": "string", + "default": 6, + }, + }, }, }, }, @@ -65,4 +70,34 @@ describe('sf-array.directive.js', function() { // tmpl.$valid.should.be.true; }); }); + + it('should not delete innocent items on delete', function(done) { + tmpl = angular.element('
'); + + inject(function($compile, $rootScope) { + var scope = $rootScope.$new(); + scope.model = { names: [{ name: "0"}, {name: "1"}, {name: "2"}, {name: "3"}]}; + + scope.schema = exampleSchema; + + scope.form = [ "*" ]; + + $compile(tmpl)(scope); + runSync(scope, tmpl); + + tmpl.find('div.help-block').text().should.equal('foobar'); + + var close = tmpl.find('button.close'); + close.eq(1).click(); + + $rootScope.$apply(); + + setTimeout(function() { + scope.model.names[0].name.should.equal("0"); + scope.model.names[1].name.should.equal("2"); + scope.model.names[2].name.should.equal("3"); + done(); + }, 0) + }); + }); }); diff --git a/src/directives/sf-field.directive.js b/src/directives/sf-field.directive.js index e327627c8..6aae444c7 100644 --- a/src/directives/sf-field.directive.js +++ b/src/directives/sf-field.directive.js @@ -308,44 +308,48 @@ export default function($parse, $compile, $interpolate, sfErrorMessage, sfPath, // If the entire schema form is destroyed we don't touch the model if (!scope.externalDestructionInProgress) { - let destroyStrategy = form.destroyStrategy || + var destroyStrategy = form.destroyStrategy || (scope.options && scope.options.destroyStrategy) || 'remove'; // No key no model, and we might have strategy 'retain' if (key && destroyStrategy !== 'retain') { - // Get the object that has the property we wan't to clear. - let obj = scope.model; - if (key.length > 1) { - obj = sfSelect(key.slice(0, key.length - 1), obj); - } - - if(obj && scope.destroyed && obj.$$hashKey && obj.$$hashKey !== scope.destroyed) { - return; - } - - // We can get undefined here if the form hasn't been filled out entirely - if (obj === undefined) { - return; - } // Type can also be a list in JSON Schema - let type = (form.schema && form.schema.type) || ''; + var type = (form.schema && form.schema.type) || ''; // Empty means '',{} and [] for appropriate types and undefined for the rest - // console.log('destroy', destroyStrategy, key, type, obj); - if (destroyStrategy === 'empty' && type.indexOf('string') !== -1) { - obj[key.slice(-1)] = ''; - } - else if (destroyStrategy === 'empty' && type.indexOf('object') !== -1) { - obj[key.slice(-1)] = {}; - } - else if (destroyStrategy === 'empty' && type.indexOf('array') !== -1) { - obj[key.slice(-1)] = []; - } - else if (destroyStrategy === 'null') { - obj[key.slice(-1)] = null; + let value; + if (destroyStrategy === 'empty') { + value = type.indexOf('string') !== -1 ? '' : + type.indexOf('object') !== -1 ? {} : + type.indexOf('array') !== -1 ? [] : undefined; + } else if (destroyStrategy === 'null') { + value = null; } - else { - delete obj[key.slice(-1)]; + + if (value !== undefined) { + sfSelect(key, scope.model, value); + } else { + // Get the object parent object + let obj = scope.model; + if (key.length > 1) { + obj = sfSelect(key.slice(0, key.length - 1), obj) + } + + // parent can be undefined if the form hasn't been filled out + // entirely + if (obj === undefined) { + return; + } + + // if parent is an array, then we have already been removed. + // set flag to all children (who are about to recieve a $destroy + // event as well) that we have already been destroyed + if (angular.isArray(obj)) { + scope.externalDestructionInProgress = true; + return; + } + + delete obj[key[key.length-1]]; } } }