2015-01-14 2 views
9

Diciamo che ho il seguente codicePuò una direttiva stessa eliminare da un ambito genitore

<div ng-app="app" ng-controller="controller"> 
<div ng-repeat="instance in instances> 
    <customDirective ng-model="instance"></customDirective> 
</div> 
</div> 

E la mia direttiva personalizzato ha un ambito isolato, definito come:

app.directive('customDirective', function($log) { 
     return { 
      restrict: 'E', 
      templateUrl: './template.htm', 
      scope: {_instance:"=ngModel"}, 
      link: function($scope) { 
      .... 
      } 
     }); 

In questa direttiva, mi avere un'opzione per eliminarlo. La mia domanda è: come posso comunicare alle istanze dell'array nell'ambito genitore e dirgli di distruggere questo oggetto e in effetti rimuovere l'istanza cancellata dal mio DOM?

Spero che abbia senso.

+0

sembra che si sta guardando all'indietro ... rimuovere l'oggetto istanza dalla gamma del modello, angolare prende cura del DOM per te – charlietfl

+0

@Matt, potresti voler spostare il tuo segno di spunta sull'altra risposta. Sembra che il consenso generale sia l'approccio preferito. –

risposta

30

secondo il New Dev in un previous comment, questo è il modo:

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>

+1

impeccabile. Liscio come nessun'altra risposta che ho visto in giro! Grazie! – Dazag

+0

Soluzione superba –

3

Innanzitutto, non utilizzare ngModel come attributo DOM. Questa è una direttiva AngularJS utilizzata per associare gli input del modulo alle variabili scope.

L'ho rinominato in model e aggiunto un attributo extra chiamato index.

<div ng-app="app" ng-controller="controller"> 
    <div ng-repeat="instance in instances> 
    <customDirective model="instance" index="$index"></customDirective> 
    </div> 
</div> 

Ora nel tuo controller che si può ascoltare per eventi (come un evento personalizzato si potrebbe titolo removeCustom) emessa dai bambini utilizzando $scope.$on().

app.controller('controller',function($scope) { 
    $scope.instances = [.....]; 
    $scope.$on('removeCustom',function($index) { 
     delete $scope.instances[$index]; 
    }); 
}); 

Poi, nel tuo direttiva personalizzato è necessario utilizzare $scope.$emit() per trasmettere la tua removeCustom evento fino la gerarchia portata al 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: Una direttiva può sempre togliere stesso chiamando $el.remove() nella funzione di collegamento, ma dal momento che la vostra direttiva è stato creato tramite un ngRepeat sarà solo ottenere ricreato nel prossimo digest. Quindi devi dire al controller di rimuoverlo dall'array instances.

+5

'$ emit' sembra inappropriato in quanto" inquina "l'ambito globale. Userei '" & "' - una chiamata di funzione dalla direttiva. –

+0

@NewDev si, sono d'accordo. Sarebbe un approccio migliore. – cgTag

+6

non utilizzare 'delete' sugli array, non rimuove l'elemento, usa' splice() 'in modo da modificare la lunghezza e non lasciare un elemento non definito nell'array. In generale è meglio passare l'oggetto reale e non fare affidamento sul suo indice di vista, che potrebbe essere diverso a causa del filtraggio, quindi usare 'indexOf' per rimuoverlo – charlietfl