Can a directive delete itself from a parent scope
Solution 1
according to New Dev in a previous comment, this is the way:
var app = angular.module('app', [])
.directive('customDirective', function($log) {
return {
restrict: 'EA',
template: '<a href="" ng-click="onRemove()">remove me {{model.n}}</a>',
scope: {
model:"=",
onRemove:"&"
}
}
})
.run(function($rootScope) {
$rootScope.instances = [{n:1},{n:2},{n:3},{n:4}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-repeat="i in instances">
<custom-directive model="i" on-remove="instances.splice($index,1)">
</custom-directive>
</div>
</div>
Solution 2
First, don't use ngModel
as a DOM attribute. This is an AngularJS directive used to bind form inputs to scope variables.
I've renamed it to model
and added an extra attribute called index
.
<div ng-app="app" ng-controller="controller">
<div ng-repeat="instance in instances>
<customDirective model="instance" index="$index"></customDirective>
</div>
</div>
Now in your controller you can listen for events (such as a custom event you might title removeCustom
) emitted by children using $scope.$on()
.
app.controller('controller',function($scope) {
$scope.instances = [.....];
$scope.$on('removeCustom',function($index) {
delete $scope.instances[$index];
});
});
Then in your custom directive you have to use $scope.$emit()
to broadcast your removeCustom
event up the scope hierarchy to the controller.
app.directive('customDirective', function($log) {
return {
restrict: 'E',
templateUrl: './template.htm',
scope: {
model:"=",
index:"="
},
link: function($scope,$el,$attr) {
// when you need to remove this
$scope.$emit('removeCustom',$scope.index);
}
});
FYI: A directive can always remove itself by calling $el.remove()
in the link function, but since your directive is created via a ngRepeat
it will just get recreated in the next digest. So you have to tell the controller to remove it from the instances
array.
Comments
-
Matt almost 2 years
Let's say I have the following code
<div ng-app="app" ng-controller="controller"> <div ng-repeat="instance in instances> <customDirective ng-model="instance"></customDirective> </div> </div>
And my custom directive has an isolated scope, defined as:
app.directive('customDirective', function($log) { return { restrict: 'E', templateUrl: './template.htm', scope: {_instance:"=ngModel"}, link: function($scope) { .... } });
In this directive, I have to option to delete it. My question is how can I communicate back to the array instances in the parent scope and tell it to destroy this object and in effect remove the deleted instance from my DOM?
Hope that makes sense.
-
New Dev over 9 years
$emit
seems inappropriate here as it "pollutes" the global scope. I would use"&"
- a function call from the directive. -
Reactgular over 9 years@NewDev yes, I agree. That would be a better approach.
-
charlietfl over 9 yearsdon't use
delete
on arrays either, it doesn't remove the element , usesplice()
so you modify length and don't leave an undefined element in the array. In general is better to pass the actual object and not rely on it's view index, which could be different due to filtering, then useindexOf
to remove it -
Michael over 9 yearsthanks to @charlietfl bc i was
delete
-ing the elem from the array in an obj, rather than splicing, d-oh! -
sg.cc over 9 yearsIs there seriously no way to make an object delete itself without it seeing its parent array? I feel like putting the array of objects into the root scope (Lautaro's comment below), or pinging an event to some external controller (this answer) are both hacks.
-
Dazag over 8 yearsflawless. Smooth like no other answer I've seen around! thanks!