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!
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];
}
})