AngularJS: come posso passare le variabili tra i controller?

Ho due controller angolari:

function Ctrl1($scope) { $scope.prop1 = "First"; } function Ctrl2($scope) { $scope.prop2 = "Second"; $scope.both = Ctrl1.prop1 + $scope.prop2; //This is what I would like to do ideally } 

Non riesco a usare Ctrl1 all’interno di Ctrl2 perché non è definito. Comunque se provo a farlo passare così …

 function Ctrl2($scope, Ctrl1) { $scope.prop2 = "Second"; $scope.both = Ctrl1.prop1 + $scope.prop2; //This is what I would like to do ideally } 

Ottengo un errore Qualcuno sa come fare questo?

fare

 Ctrl2.prototype = new Ctrl1(); 

Inoltre fallisce.

NOTA: questi controller non sono nidificati l’uno dentro l’altro.

Un modo per condividere le variabili tra più controller è creare un servizio e inserirlo in qualsiasi controller in cui si desidera utilizzarlo.

Esempio di servizio semplice:

 angular.module('myApp', []) .service('sharedProperties', function () { var property = 'First'; return { getProperty: function () { return property; }, setProperty: function(value) { property = value; } }; }); 

Utilizzo del servizio in un controller:

 function Ctrl2($scope, sharedProperties) { $scope.prop2 = "Second"; $scope.both = sharedProperties.getProperty() + $scope.prop2; } 

Questo è descritto molto bene in questo blog (Lezione 2 e in particolare).

Ho scoperto che se si desidera associare a queste proprietà tra più controller, funziona meglio se si esegue il binding alla proprietà di un object anziché a un tipo primitivo (booleano, stringa, numero) per mantenere il riferimento associato.

Esempio: var property = { Property1: 'First' }; invece di var property = 'First'; .


AGGIORNAMENTO: Per (si spera) rendere le cose più chiare ecco un violino che mostra un esempio di:

  • Associazione a copie statiche del valore condiviso (in myController1)
    • Associazione a una primitiva (stringa)
    • Associazione alla proprietà di un object (salvata in una variabile di ambito)
  • Associazione a valori condivisi che aggiornano l’interfaccia utente man mano che i valori vengono aggiornati (in myController2)
    • Associazione a una funzione che restituisce una primitiva (stringa)
    • Associazione alla proprietà dell’object
    • Associazione bidirezionale alla proprietà di un object

Mi piace illustrare cose semplici con semplici esempi 🙂

Ecco un esempio di Service molto semplice:

 angular.module('toDo',[]) .service('dataService', function() { // private variable var _dataObj = {}; // public API this.dataObj = _dataObj; }) .controller('One', function($scope, dataService) { $scope.data = dataService.dataObj; }) .controller('Two', function($scope, dataService) { $scope.data = dataService.dataObj; }); 

E qui il jsbin

Ed ecco un esempio di Factory molto semplice:

 angular.module('toDo',[]) .factory('dataService', function() { // private variable var _dataObj = {}; // public API return { dataObj: _dataObj }; }) .controller('One', function($scope, dataService) { $scope.data = dataService.dataObj; }) .controller('Two', function($scope, dataService) { $scope.data = dataService.dataObj; }); 

E qui il jsbin


Se è troppo semplice, ecco un esempio più sofisticato

Vedi anche la risposta qui per i commenti relativi alle migliori pratiche

— So che questa risposta non è per questa domanda, ma voglio le persone che leggono questa domanda e vogliono gestire Servizi come Fabbriche per evitare problemi nel fare questo —-

Per questo dovrai usare un servizio o una fabbrica.

I servizi sono la MIGLIORE PRATICA per condividere i dati tra controllori non annidati.

Un’annotazione molto buona su questo argomento sulla condivisione dei dati è come dichiarare gli oggetti. Sono stato sfortunato perché sono caduto in una trappola AngularJS prima di aver letto su di esso, ed ero molto frustrato. Quindi lascia che ti aiuti a evitare questo problema.

Ho letto dal libro “ng-book: The complete on AngularJS” che i modelli ng di AngularJS creati nei controller come dati nudi sono SBAGLIATI!

Un elemento $ scope dovrebbe essere creato in questo modo:

 angular.module('myApp', []) .controller('SomeCtrl', function($scope) { // best practice, always use a model $scope.someModel = { someValue: 'hello computer' }); 

E non così:

 angular.module('myApp', []) .controller('SomeCtrl', function($scope) { // anti-pattern, bare value $scope.someBareValue = 'hello computer'; }; }); 

Questo perché è consigliato (BEST PRACTICE) per il DOM (documento html) per contenere le chiamate come

 
//NOTICE THE DOT.

Questo è molto utile per i controller annidati se si desidera che il controller figlio sia in grado di modificare un object dal controller principale ….

Ma nel tuo caso non vuoi ambiti nidificati, ma c’è un aspetto simile per ottenere oggetti dai servizi ai controller.

Diciamo che hai il tuo servizio ‘Factory’ e nello spazio di ritorno c’è un objectA che contiene l’object B che contiene objectC.

Se dal tuo controller vuoi OTTENERE l’objectC nel tuo scope, è un errore dire:

 $scope.neededObjectInController = Factory.objectA.objectB.objectC; 

Non funzionerà … Invece userà solo un punto.

 $scope.neededObjectInController = Factory.ObjectA; 

Quindi, nel DOM è ansible chiamare objectC dall’objectA. Questa è una best practice relativa alle fabbriche e, cosa più importante, aiuterà ad evitare errori imprevisti e non rilevabili.

Soluzione senza creare il servizio, utilizzando $ rootScope:

Per condividere le proprietà tra i controller dell’app, puoi utilizzare Angular $ rootScope. Questa è un’altra opzione per condividere i dati, mettendoli in modo che la gente ne sia a conoscenza.

Il modo preferito per condividere alcune funzionalità tra i controller è Servizi, per leggere o modificare una proprietà globale è ansible utilizzare $ rootcope.

 var app = angular.module('mymodule',[]); app.controller('Ctrl1', ['$scope','$rootScope', function($scope, $rootScope) { $rootScope.showBanner = true; }]); app.controller('Ctrl2', ['$scope','$rootScope', function($scope, $rootScope) { $rootScope.showBanner = false; }]); 

Utilizzo di $ rootScope in un modello (Proprietà di accesso con $ root):

 

L’esempio sopra ha funzionato come un fascino. Ho appena fatto una modifica nel caso in cui ho bisogno di gestire più valori. Spero che aiuti!

 app.service('sharedProperties', function () { var hashtable = {}; return { setValue: function (key, value) { hashtable[key] = value; }, getValue: function (key) { return hashtable[key]; } } }); 

Tendo ad usare i valori, felice per chiunque di discutere perché questa è una ctriggers idea ..

 var myApp = angular.module('myApp', []); myApp.value('sharedProperties', {}); //set to empty object - 

Quindi iniettare il valore come da un servizio.

Imposta in ctrl1:

 myApp.controller('ctrl1', function DemoController(sharedProperties) { sharedProperties.carModel = "Galaxy"; sharedProperties.carMake = "Ford"; }); 

e accesso da Ctrl2:

 myApp.controller('ctrl2', function DemoController(sharedProperties) { this.car = sharedProperties.carModel + sharedProperties.carMake; }); 

Mi piacerebbe contribuire a questa domanda sottolineando che il modo consigliato di condividere i dati tra i controller e persino le direttive, è usando i servizi (le fabbriche) come è stato già sottolineato, ma vorrei anche fornire un un esempio pratico di come dovrebbe essere fatto.

Ecco il plunker funzionante: http://plnkr.co/edit/Q1VdKJP2tpvqqJL1LF6m?p=info

Innanzitutto, crea il tuo servizio , che avrà i tuoi dati condivisi :

 app.factory('SharedService', function() { return { sharedObject: { value: '', value2: '' } }; }); 

Quindi, semplicemente inseriscilo nei controller e acquisisci i dati condivisi nel tuo ambito:

 app.controller('FirstCtrl', function($scope, SharedService) { $scope.model = SharedService.sharedObject; }); app.controller('SecondCtrl', function($scope, SharedService) { $scope.model = SharedService.sharedObject; }); app.controller('MainCtrl', function($scope, SharedService) { $scope.model = SharedService.sharedObject; }); 

Puoi farlo anche per le tue direttive , funziona allo stesso modo:

 app.directive('myDirective',['SharedService', function(SharedService){ return{ restrict: 'E', link: function(scope){ scope.model = SharedService.sharedObject; }, template: '
' } }]);

Spero che questa risposta pratica e pulita possa essere d’aiuto a qualcuno.

L’esempio seguente mostra come passare le variabili tra i controller di fratelli e prendere un’azione quando il valore cambia.

Esempio di caso d’uso: si ha un filtro in una barra laterale che modifica il contenuto di un’altra vista.

 angular.module('myApp', []) .factory('MyService', function() { // private var value = 0; // public return { getValue: function() { return value; }, setValue: function(val) { value = val; } }; }) .controller('Ctrl1', function($scope, $rootScope, MyService) { $scope.update = function() { MyService.setValue($scope.value); $rootScope.$broadcast('increment-value-event'); }; }) .controller('Ctrl2', function($scope, MyService) { $scope.value = MyService.getValue(); $scope.$on('increment-value-event', function() { $scope.value = MyService.getValue(); }); }); 
  

Controller 1 Scope


Controller 2 Scope

Value: {{ value }}

Non potresti anche rendere la proprietà parte degli ambiti genitore?

 $scope.$parent.property = somevalue; 

Non sto dicendo che sia giusto ma funziona.

Ah, ho un po ‘di questa roba nuova come altra alternativa. È un magazzino locale e lavora dove lavora angolarmente. Prego. (Ma davvero, grazie al ragazzo)

https://github.com/gsklee/ngStorage

Definisci i tuoi valori di default:

 $scope.$storage = $localStorage.$default({ prop1: 'First', prop2: 'Second' }); 

Accedi ai valori:

 $scope.prop1 = $localStorage.prop1; $scope.prop2 = $localStorage.prop2; 

Memorizza i valori

 $localStorage.prop1 = $scope.prop1; $localStorage.prop2 = $scope.prop2; 

Ricordarsi di inserire ngStorage nella propria app e $ localStorage nel controller.

Potresti farlo con servizi o fabbriche. Sono essenzialmente gli stessi a parte per alcune differenze fondamentali. Ho trovato questa spiegazione su thinkster.io per essere la più facile da seguire. Semplice, al punto ed efficace.

Ci sono due modi per farlo

1) Utilizzare il servizio get / set

2) $scope.$emit('key', {data: value}); //to set the value $scope.$emit('key', {data: value}); //to set the value

  $rootScope.$on('key', function (event, data) {}); // to get the value 

Secondo approccio:

 angular.module('myApp', []) .controller('Ctrl1', ['$scope', function($scope) { $scope.prop1 = "First"; $scope.clickFunction = function() { $scope.$broadcast('update_Ctrl2_controller', $scope.prop1); }; } ]) .controller('Ctrl2', ['$scope', function($scope) { $scope.prop2 = "Second"; $scope.$on("update_Ctrl2_controller", function(event, prop) { $scope.prop = prop; $scope.both = prop + $scope.prop2; }); } ]) 

Html:

 

{{both}}

Per maggiori dettagli vedi plunker:

http://plnkr.co/edit/cKVsPcfs1A1Wwlud2jtO?p=preview

Se non vuoi fare un servizio allora puoi fare così.

 var scope = angular.element("#another ctrl scope element id.").scope(); scope.plean_assign = some_value; 

Oltre a $ rootScope e servizi, esiste una soluzione alternativa semplice e pulita per estendere angular per aggiungere i dati condivisi:

nei controller:

 angular.sharedProperties = angular.sharedProperties || angular.extend(the-properties-objects); 

Queste proprietà appartengono all’object “angular”, separate dagli ambiti e possono essere condivise in ambiti e servizi.

1 vantaggio che non devi iniettare l’object: sono accessibili ovunque immediatamente dopo la tua definizione!