2

My problem is similar to the one in this question, This works when we know the scope variable to remove. However I am looking for something generic, like remove the variable for all the elements this directive is attached to, whenever they become hidden. I tried injecting the ngModel and tried setting to null or delete, doesn't seem to work.

This is what I am trying to to: plunk

myModule.directive('destroyY', function(){
         return{
          restrict:'A',
          require: '?ngModel',
          link: function(scope, elem, attrs, ngModel) {

            scope.$on('$destroy', function(){
             console.log(ngModel);

             ngModel=null; // doesn't work
             delete ngModel; // doesn't work

            }) 
          }
         }
        });

Any help is greatly appreciated. Thanks!

Community
  • 1
  • 1
Narain Mittal
  • 1,150
  • 11
  • 25

1 Answers1

3

Specifically, in your case of a directive that works with ng-if and uses require: "ngModel", you could do:

 scope.$on("$destroy", function(){
    ngModel.$setViewValue(undefined);
 }

Just a one other thing to note here:

scope.$on("$destroy") works when the scope is destroyed - not always when the element is "destroyed" (or removed from DOM). In you case it works since ng-if creates a child scope, however, it is entirely possible that an element is removed by another directive without the scope that it "lived" it being destroyed. In this case, you might want to use elem.on("$destroy").

EDIT:

Indeed, as noted in the comments, this does NOT remove the actual key - just sets the value of that key. If you think about it, this is the right thing to do, because the key could be a setter function (ngModel supports setter/getter functions).

Although I recommend against that, you could still remove the property from the scope, although it is an ugly approach that is obviously not catered to by Angular.

You need to get the parent object expression (e.g. form) and its property expression (e.g. y) and then delete the property. Notice that if there is no dot notation ("."), then ngModel would have set the value on the scope being destroyed, and so we would care about it. To do that, you'd need to use $parse:

var modelExp = attrs.ngModel;
var idxOfDot = modelExp.lastIndexOf(".");
var parentExp = modelExp.substring(0, idxOfDot);
var propExp = modelExp.substring(idxOfDot + 1);

var parsedParentExp = $parse(parentExp);

scope.$on("$destroy", function(){
   var p = parsedParentExp(scope);
   if (p){
      delete p[propExp];
   }
})
New Dev
  • 48,427
  • 12
  • 87
  • 129
  • Thanks! that sets the value to undefined, So when we see the output it will be _{x:6;y:undefined}_ but I was looking at if somehow we can remove the element Y from the model itself. i.e. output as _{x:6}_ and to do that not just for y but to every element this directive is attached to. I hope I'm making some sense... – Narain Mittal May 18 '15 at 22:09
  • @NarainMittal, clearly you haven't tried it - this will remove the property – New Dev May 18 '15 at 22:25
  • Actually I did before commenting, Also updated the plunk with your solution. You can have a look. – Narain Mittal May 19 '15 at 20:05
  • @NarainMittal, hmm... you're right. I was only working with `{{form}}` - that actually doesn't display `undefined` keys. So, you are right - it doesn't remove, which actually, if you think about is the right thing to do. See the updated answer. Still, though, please revert the plunk so that the original question is intact – New Dev May 19 '15 at 21:39
  • Thansk for the workaround! I will see if can get around the requirement to delete the element. – Narain Mittal May 21 '15 at 01:58