9

aggiornamento: deve essere stato qualcosa di stupido in un'altra parte del codice. Funziona ora, quindi la sintassi bindToController va bene.AngularJS 1.4 direttive: scope, a due vie vincolante e bindToController

Stiamo utilizzando AngularJS 1.4, che ha introdotto un new way to use bindToController in direttive.

Dopo un bel po 'di lettura (e forse non capire tutto), abbiamo definito la nostra direttiva come questa:

.directive('mdAddress', function mdAddress() { 
    var directive = { 
     restrict: 'EA', 
     scope: {}, 
     bindToController: { 
     address: '=' 
     }, 
     templateUrl: 'modules/address/address.html', 
     controller: AddressController, 
     controllerAs: 'dir' 
    }; 

Chiamarlo da un'altra vista in questo modo:

<md-address address="vm.address"></md-address> 

Avendo già definito nel controller della vista:

vm.address = { 
    street: null, 
    countryCode: null, 
    cityCode: null, 
    postalCode: null 
    }; 

Riferimento alle variabili in th e direttiva modello come questa:

<md-input-container> 
    <label>{{'ADDRESSNUMBER' | translate}}</label> 
    <input type="number" ng-model="dir.address.streetNumber"> 
    </md-input-container> 

Abbiamo trascorso 4 ore cercando di capire perché la nostra direttiva non funzionava. Bene, funzionava, ma il collegamento bidirezionale tra il controller e la direttiva non lo era, vm.address.street era irrimediabilmente impostato su null.

Dopo un po ', abbiamo appena provato il vecchio modo:

.directive('mdAddress', function mdAddress() { 
    var directive = { 
     restrict: 'EA', 
     scope: { 
     address: '=' 
     }, 
     bindToController: true, 
     templateUrl: 'modules/address/address.html', 
     controller: AddressController, 
     controllerAs: 'dir' 
    }; 

E magicamente funzionato. Qualche idea PERCHÉ?

+0

Cosa hai nel tuo modello 'modules/address/address.html'? Se si sta tentando di fare riferimento a 'vm' nel modello, ciò causerebbe un problema nullo poiché' vm' non esiste nell'ambito della direttiva. Anche se si stava tentando di associare semplicemente 'indirizzo' nel modello direttiva, anche questo non esisterebbe dato che si sta vincolando il controller come' dir', quindi dovrebbe essere 'dir.address' –

+0

In il modello abbiamo fatto riferimento agli elementi con 'dir':' '. Ho modificato il post principale per chiarire questo. Grazie. – LeoLozes

+0

Per favore, fornire due plunkers, per entrambi i casi. C'è una spiegazione semplice per questo, ma il testo in chiaro non dà un'idea chiara di ciò che hai fatto esattamente. – estus

risposta

18

Aggiornamento:

Grazie al reference to this blog post, ho bisogno di aggiornare la mia risposta. Dal AngularJS 1.4 sembra davvero, che è possibile utilizzare

scope: {}, 
bindToController: { 
    variable: '=' 
} 

, che farà il (esatto) stessa cosa che la vecchia sintassi:

scope: { 
    variable: '=' 
}, 
bindToController: true 

Le linee utili dal codice AngularJS fonte per spiegare questo comportamento:

if (isObject(directive.scope)) { 
    if (directive.bindToController === true) { 
    bindings.bindToController = parseIsolateBindings(directive.scope, 
                directiveName, true); 
    bindings.isolateScope = {}; 
    } else { 
    bindings.isolateScope = parseIsolateBindings(directive.scope, 
               directiveName, false); 
    } 
} 
if (isObject(directive.bindToController)) { 
    bindings.bindToController = 
     parseIsolateBindings(directive.bindToController, directiveName, true); 
} 

Fonte: AngularJS 1.4.0

Risposta originale:

Spero di poterti spiegare perché questo comportamento che hai riscontrato sia corretto e in cui hai sbagliato a comprendere il concetto di oscilloscopio.

Mi spiego meglio, quello che hai fatto nel tuo primo frammento di codice:

.directive('mdAddress', function mdAddress() { 
    var directive = { 
     restrict: 'EA', 
     scope: {}, 
     bindToController: { 
     address: '=' 
     }, 
     templateUrl: 'modules/address/address.html', 
     controller: AddressController, 
     controllerAs: 'dir' 
    }; 

Con scope: {}, è stato creato un ambito isolato (senza alcuna eredità) per la direttiva mdAddress. Ciò significa che non vengono trasmessi dati tra il controller principale e la direttiva.

Avendo questo in mente, per quanto riguarda il secondo frammento di codice:

<md-address address="vm.address"></md-address> 

vm.address dal controller genitore/Vista saranno assegnati come espressione per l'attributo di indirizzo della direttiva, ma come si definito un ambito isolato prima , i dati non vengono passati a AddressController e pertanto non sono disponibili nel valore bindToController.

Pensiamo alla definizione dell'oggetto scope come a "quali dati verranno passati" e allo bindToController come "quali dati saranno disponibili nell'oggetto controllerA vista di mia vista".

Così, ora diamo uno sguardo all'ultimo (e il codice di lavoro frammento di):

.directive('mdAddress', function mdAddress() { 
    var directive = { 
     restrict: 'EA', 
     scope: { 
     address: '=' 
     }, 
     bindToController: true, 
     templateUrl: 'modules/address/address.html', 
     controller: AddressController, 
     controllerAs: 'dir' 
    }; 

C'è stato creato un ambito isolato, troppo, ma questa volta si è aggiunto l'attributo address da passato come un espressione. Così ora lo address passato dalla vista nel secondo frammento sarà disponibile nell'ambito del controllore. Impostando ora bindToController: true, si associeranno tutte le proprietà dell'ambito corrente al controller (o più probabilmente all'oggetto controllerAs). E ora funziona come ci si aspetterebbe, perché i dati verranno passati all'ambito e i dati verranno passati all'ambito del modello del controllore.

Questa breve panoramica consente di comprendere meglio il concetto degli oggetti di definizione scope e bindToController?

+0

Grazie mille per la tua risposta! Ha senso, e capisco perfettamente la seconda parte della tua spiegazione, ma la prima parte sembra dire letteralmente il contrario dell'articolo che ho collegato (sulla nuova funzionalità bindToController). Specialmente quando dice "Questo significa che possiamo spostare il nostro scope: {name: '='} ad esempio l'associazione a esso per rendere più esplicito che i binding di isolare sono di fatto ereditati e legati al controller", e sostituisce'scope: { nome: '='}, bindToController: true' con 'scope: {}, bindToController: {name: '='}'. – LeoLozes

+0

Infatti, grazie per la vostra risposta. Hai ragione, ho bisogno di ripristinare parti della mia risposta. La linea importante è quella del codice sorgente AngularJS menzionato nell'articolo - quindi il comportamento dovrebbe essere lo stesso in entrambi i casi. Quindi forse hai davvero qualche bug/errore di battitura nel tuo codice? O puoi riprodurre tutto dalla tua domanda? Argomento molto interessante! – ConcurrentHashMap

+0

Grazie, ho pensato di aver frainteso l'articolo :). Ad ogni modo, rivedendo il codice AngularJS, potrebbe essere che 'scope: {}' restituisca 'isObject' come vero, dal momento che è un oggetto vuoto, non' null'? Quindi entrerebbe nella prima parte del 'if'sentence ... Ho controllato il codice sorgente di AngularJS per' isObject' ma non sono sicuro ... – LeoLozes