2015-04-26 9 views
5

Esiste un trucco per ottenere l'elemento associato all'ambito al di fuori della direttiva che lo possiede?Ottieni l'elemento dell'ambito all'esterno della direttiva

Agisco sulla premessa che deve essere fatto in condizioni meno favorevoli (dalla console o dallo script di Greasemonkey). Per esempio. per ottenere l'elemento che ha lo scopo

angular.element(document.querySelector('.ng-scope')).scope().$$childTail 

senza DOM che attraversa.

Suppongo che sia possibile attraversare tutti gli elementi DOM ng-scope ee mappare i loro ambiti, ma sto cercando una soluzione più elegante (la mappa deve anche essere aggiornata e sto cercando di rimanere via da DOMSubtreeModified, anche questo non funzionerà con debugInfoEnabled disattivato).

+1

Non hai bisogno di alcun ambito se conosci l'id dell'elemento –

+0

Ma come mai? – estus

+0

fammi riformulare la domanda, stai usando Batarang? –

risposta

7

Gli ambiti (src) non mantengono un riferimento all'elemento a cui sono associati. Dopo tutto, gli ambiti possono esistere senza essere associati a un elemento specifico.

$ compile (src) è l'unico responsabile per l'associazione di elementi con ambiti.

Parte del processo di compilazione aumenta l'elemento, consentendo di passare dall'elemento >> ambito (ad esempio angular.element("#something").scope()). Lo stesso non sembra accadere con gli ambiti.

Quindi, per andare nell'altro senso, ambito >> elemento, è necessario mappare gli ID ambito: Get DOM element by scope $id. Quella caratteristica di Angular JS Batarang che ti permette di scegliere un elemento dalla pagina e ispezionare l'ambito ad esso associato? Questo è come è fatto. Batarang usa il suggerimento angolare. angular-hint esegue un'iterazione di tutti gli elementi della pagina con una classe ng-scope e restituisce quello con un ID ambito corrispondente (src: function findElt).

function findElt (scopeId) { 
    var elts = document.querySelectorAll('.ng-scope'); 
    var elt, scope; 

    for (var i = 0; i < elts.length; i++) { 
    elt = angular.element(elts[i]); 
    scope = elt.scope(); 
    if (scope.$id === scopeId) { 
     return elt; 
    } 
    } 
} 
+0

In passato ho avuto problemi di prestazioni con DOMSubtreeModified con approccio simile, speriamo che gli osservatori di mutazione, il caching e la limitazione possano aiutare. Grazie per aver migliorato la risposta con riferimenti angolari, l'ho trascurato. – estus

0

Ci sono alcune cose che puoi fare per ottenere l'elemento di una direttiva.

Element on dell'evento

Se è necessario passare l'elemento su un evento, è possibile creare un callback che può passare l'elemento posteriore. Se non hai bisogno di un riferimento per tutto il tempo, questo è il metodo preferito.

In ritorni oggetto nella direttiva, aggiungere qualcosa di simile

scope:{ 
     elementclicked: "&" 
    } 

Nel modello del vostro direttiva, è possibile aggiungere

<....... ng-click="ElementClicked(event)"........> 

Nella direttiva Controller, ora è possibile gestire il clic e passa i risultati

$scope.ElementClicked = function ($event) { 
    if ($scope.elementclicked != undefined) { 
     elementclicked({ event: $event }); 
    } 
} 

Ora si passa il callback come qualsiasi altro alla DIRETTIVA.

<yourDirective elementclicked="MyFunction(event)" ....> 

elemento quando collegato

Se avete bisogno di un riferimento al momento della creazione, si può fare anche questo. Se passi in una struttura dati come le impostazioni, puoi impostarlo nell'evento di collegamento.Quando fai il tuo link nella direttiva, imposta semplicemente l'elemento.

scope:{ 
     settings:"=" 
}, 
link:function(scope,element){ 
    scope.$watch('settings',function(){ 
     if(scope.settings!=undefined){ 
      scope.settings.element=element; 
     } 
} 
} 

Questo controllerà quando le impostazioni sono vincolate e imposta la proprietà dell'elemento. Il grande svantaggio è che si aggiunge una proprietà a un oggetto passato, ma se si tratta di una direttiva all'interno di una direttiva o è solo il tuo progetto, dovrebbe andare bene.

Un altro modo per farlo sarebbe utilizzare il primo metodo e creare un callback con elementi (elementi) e attivarlo dopo aver collegato l'ambito.

+0

La risposta è abbastanza descrittiva ma risponde al soggetto della domanda, non alla domanda stessa. – estus

0

Quello che ho capito, si desidera accedere al valore dell'ambito al di fuori della direttiva. Ho fatto un piccolo smaple, check it:

Parte HTML:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> 
<script data-require="[email protected]" src="https://code.angularjs.org/1.3.15/angular.js" data-semver="1.3.15"></script> 

    <div id="outer" ng-app="plunker" ng-controller="MainCtrl"> 
    You are {{msg}} 
</div> 
<div onclick="change()">click me</div> 

Scipt parte:

var app = angular.module('plunker', []); 

    app.controller('MainCtrl', function($scope, $rootScope) { 
    $scope.msg = "great"; 
     $rootScope.safeApply = function(fn) { 
      var phase = this.$root.$$phase; 
      if(phase == '$apply' || phase == '$digest') { 
       if(fn) { 
        fn(); 
       } 
      } else { 
       this.$apply(fn); 
      } 
     }; 
    }); 

// Java personalizzato sceneggiatura

function change() { 
    var scope = angular.element($("#outer")).scope(); 
    scope.safeApply(function(){ 
     scope.msg = 'Superhero'; 
    }) 
} 

Per il codice di sopra di lavoro Il collegamento Plunker è qui: Plunker

Problemi correlati