2014-06-17 23 views
10

Sto avendo difficoltà di capire come posso definire una direttiva personalizzato che entrambi:direttiva angolare: usando ng-modello nel campo di applicazione isolare

  1. usi isolare campo di applicazione, e
  2. utilizza la direttiva ng-modello in un nuovo ambito all'interno del suo modello.

Ecco un esempio:

HTML:

<body ng-app="app"> 
    <div ng-controller="ctrl"> 
    <dir model="foo.bar"></dir> 
    Outside directive: {{foo.bar}} 
    </div> 
</body> 

JS:

var app = angular.module('app',[]) 
    .controller('ctrl', function($scope){ 
    $scope.foo = { bar: 'baz' }; 
    }) 
    .directive('dir', function(){ 
    return { 
     restrict: 'E', 
     scope: { 
     model: '=' 
     }, 
     template: '<div ng-if="true"><input type="text" ng-model="model" /><br/></div>' 
    } 
    }); 

Il comportamento desiderato ecco che il valore dell'ingresso è legato alla proprietà del perimetro esterno foo.bar, tramite la proprietà model dell'ambito (isolato) della direttiva. Ciò non accade, perché la direttiva ng-if sul div che racchiude il modello crea un nuovo ambito, quindi è lo model dello scope che viene aggiornato, non lo scope della direttiva. Solitamente risolvi questi problemi con il modello ng assicurandoti che ci sia un punto nell'espressione, ma non riesco a vedere alcun modo per farlo qui. Mi chiedevo se potrei essere in grado di usare qualcosa di simile per la mia direttiva:

{ 
    restrict: 'E', 
    scope: { 
    model: { 
     value: '=model' 
    } 
    }, 
    template: '<div ng-if="true"><input type="text" ng-model="model.value" /><br/></div>' 
} 

ma questo non funziona ...

Plunker

risposta

9

Hai ragione - ng-if crea un ambito secondario che causa un problema quando il testo viene inserito nel campo di testo di input. Crea una proprietà shadow denominata 'model' nell'oscilloscopio secondario, che è una copia della variabile dell'ambito padre con lo stesso nome, interrompendo in modo efficace il bind del modello a due vie.

La correzione per questo è semplice. Nel modello, specificare il prefisso $ genitore:

template: '<div ng-if="true"> 
        <input type="text" ng-model="$parent.model" /><br/> 
      </div>' 

Questo assicura che si risolverà 'modello' dal campo di applicazione $ genitore, che hai già configurato per il modello a due vie vincolante attraverso l'ambito isolato.

Alla fine, il "." in ng-model salva il giorno. Trovo utile pensare a tutto ciò che rimane del punto come un modo per Angular per risolvere la proprietà attraverso l'ereditarietà dell'ambito. Senza il punto, la risoluzione della proprietà diventa un problema solo quando assegniamo le variabili di ambito (in caso contrario, le ricerche vanno bene, comprese le espressioni di binding {{model}} di sola lettura).

+1

Grazie - mi ero completamente dimenticato di $ genitore.Questo risolve il mio problema in questo caso, ma sono ancora un po 'titubante su questo come una soluzione generica: significa che devo tenere traccia di dove vengono introdotti nuovi ambiti nei miei modelli e quale livello della gerarchia ho bisogno di target, che sembra piuttosto soggetto a errori ... – Duncan

+0

Sono d'accordo con te. Misko ha spiegato che qualcuno registra un bug su questo argomento una volta a settimana - non è un bug, è il modo in cui funziona l'eredità prototipale. Per impostare correttamente ng-model, è necessario sapere come funziona l'ereditarietà dell'ambito a un livello più profondo e anche quali direttive creeranno ambiti figlio. Non riesco a pensare ad un modo migliore però. – pixelbits

+0

Sì, equo punto, anche se credo che quello che stavo ottenendo è che c'è un problema particolare con l'uso di ng-model = "$ parent.bar" in opposizione a ng-model = "foo.bar", in quello con il precedente Devo sempre pensare a dove vengono creati gli ambiti figlio, mentre con quest'ultimo non lo faccio (a patto che possa presumere che nessun ambito figlio abbia una proprietà chiamata 'pippo'). – Duncan

0

ng-if crea un ulteriore ambito prototypally ereditare, così ng-model="model" si associa alla proprietà ereditata del nuovo ambito e non alla proprietà binded bidirezionale dell'ambito della direttiva.

Cambiarlo in ng-show e sarà work.

È possibile utilizzare a small Firebug extension che ho scritto per ispezionare gli ambiti angolari.

+0

Sì, capisco che è quello che sta succedendo - ho usato ng-se apposta solo per dimostrare il problema – Duncan

Problemi correlati