371 Stimmen

Daten zwischen AngularJS Controllern teilen

Ich versuche, Daten zwischen Controllern zu teilen. Ein Anwendungsfall ist ein mehrstufiges Formular, Daten, die in eine Eingabe eingegeben werden, werden später an mehreren Anzeigeorten außerhalb des ursprünglichen Controllers verwendet. Der Code unten und in diesem jsfiddle.

HTML

    Eingabe ist: {{FirstName}}

    Eingabe sollte auch hier sein: {{FirstName}}

JS

// App ohne Abhängigkeiten deklarieren
var myApp = angular.module('myApp', []);

// Eine Factory erstellen, um Daten zwischen Controllern zu teilen
myApp.factory('Data', function(){
    // Ich weiß, dass dies nicht funktioniert, aber was wird?
    var FirstName = '';
    return FirstName;
});

// Controller für Schritt 1
myApp.controller('FirstCtrl', function( $scope, Data ){

});

// Controller für Schritt 2
myApp.controller('SecondCtrl', function( $scope, Data ){
    $scope.FirstName = Data.FirstName;
});

Jede Hilfe wird sehr geschätzt.

483voto

tasseKATT Punkte 38470

Eine einfache Lösung besteht darin, dass Ihre Factory ein Objekt zurückgibt und Ihre Controller mit einer Referenz zum selben Objekt arbeiten:

JS:

// die App ohne Abhängigkeiten deklarieren
var myApp = angular.module('myApp', []);

// Die Factory erstellen, die das Fact teilen
myApp.factory('Fact', function(){
  return { Field: '' };
});

// Zwei Controller, die ein Objekt teilen, das einen String enthält
myApp.controller('FirstCtrl', function( $scope, Fact ){
  $scope.Alpha = Fact;
});

myApp.controller('SecondCtrl', function( $scope, Fact ){
  $scope.Beta = Fact;
});

HTML:

    Erste {{Alpha.Field}}

    Zweite {{Beta.Field}}

Demo: http://jsfiddle.net/HEdJF/

Wenn Anwendungen größer, komplexer und schwerer zu testen werden, möchten Sie möglicherweise nicht das gesamte Objekt aus der Factory auf diese Weise offenlegen, sondern stattdessen begrenzten Zugriff beispielsweise über Getter und Setter geben:

myApp.factory('Data', function () {

    var data = {
        FirstName: ''
    };

    return {
        getFirstName: function () {
            return data.FirstName;
        },
        setFirstName: function (firstName) {
            data.FirstName = firstName;
        }
    };
});

Mit diesem Ansatz liegt es an den verbrauchenden Controllern, die Factory mit neuen Werten zu aktualisieren und Änderungen zu überwachen, um sie zu erhalten:

myApp.controller('FirstCtrl', function ($scope, Data) {

    $scope.firstName = '';

    $scope.$watch('firstName', function (newValue, oldValue) {
        if (newValue !== oldValue) Data.setFirstName(newValue);
    });
});

myApp.controller('SecondCtrl', function ($scope, Data) {

    $scope.$watch(function () { return Data.getFirstName(); }, function (newValue, oldValue) {
        if (newValue !== oldValue) $scope.firstName = newValue;
    });
});

HTML:

  Eingabe ist : {{firstName}}

  Eingabe sollte auch hier sein: {{firstName}}

Demo: http://jsfiddle.net/27mk1n1o/

71voto

bennick Punkte 1879

Ich ziehe es vor, dafür $watch nicht zu verwenden. Anstatt dem gesamten Service den Bereich eines Controllers zuzuweisen, können Sie nur die Daten zuweisen.

JS:

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

myApp.factory('MyService', function(){
  return {
    data: {
      firstName: '',
      lastName: ''
    }
    // Andere Methoden oder Objekte können hier platziert werden
  };
});

myApp.controller('FirstCtrl', function($scope, MyService){
  $scope.data = MyService.data;
});

myApp.controller('SecondCtrl', function($scope, MyService){
   $scope.data = MyService.data;
});

HTML:

  Eingabe ist: {{data.firstName}}

  Eingabe sollte auch hier sein: {{data.firstName}}

Alternativ können Sie die Service-Daten mit einer direkten Methode aktualisieren.

JS:

// Eine neue Factory mit einer Update-Methode
myApp.factory('MyService', function(){
  return {
    data: {
      firstName: '',
      lastName: ''
    },
    update: function(first, last) {
      // Verbessern Sie diese Methode bei Bedarf
      this.data.firstName = first;
      this.data.lastName = last;
    }
  };
});

// Ihr Controller kann die Update-Methode des Services verwenden
myApp.controller('SecondCtrl', function($scope, MyService){
   $scope.data = MyService.data;

   $scope.updateData = function(first, last) {
     MyService.update(first, last);
   }
});

12voto

Ayush Mishra Punkte 223

Es gibt viele Möglichkeiten, wie Sie Daten zwischen Controllern teilen können

  1. Verwendung von Services
  2. Verwendung von $state.go-Services
  3. Verwendung von StateParams
  4. Verwendung von Roots cope

Erklärung jeder Methode:

  1. Ich werde es nicht erklären, da es bereits von jemandem erklärt wurde

  2. Verwendung von $state.go

      $state.go('book.name', {Name: 'XYZ'}); 
    
      // dann Parameter aus der URL abrufen
      $state.params.Name;
  3. $stateParams funktionieren ähnlich wie $state.go, Sie übergeben es als Objekt vom Absender-Controller und sammeln es im Empfänger-Controller mit StateParams

  4. Verwendung von $rootScope

    (a) Senden von Daten vom Kind- zum Eltern-Controller

      $scope.Save(Obj,function(data) {
          $scope.$emit('savedata',data); 
          // Daten als zweiten Parameter übergeben
      });
    
      $scope.$on('savedata',function(event,data) {
          // Daten als zweiten Parameter empfangen
      }); 

    (b) Senden von Daten vom Eltern- zum Kind-Controller

      $scope.SaveDB(Obj,function(data){
          $scope.$broadcast('savedata',data);
      });
    
      $scope.SaveDB(Obj,function(data){`enter code here`
          $rootScope.$broadcast('saveCallback',data);
      });

8voto

ojus kulkarni Punkte 1798

Es gibt mehrere Möglichkeiten, Daten zwischen Controllern zu teilen

  • Angular-Services
  • $broadcast, $emit-Methode
  • Kommunikation vom Eltern- zum Kindcontroller
  • $rootscope

Wie wir wissen, ist $rootscope keine bevorzugte Methode für den Datentransfer oder die Kommunikation, da es ein globaler Bereich ist, der für die gesamte Anwendung verfügbar ist

Für den Datenaustausch zwischen Angular-Js-Controllern sind Angular-Services bewährte Praktiken, z.B. .factory, .service
Für Referenz

Im Falle des Datenimports vom Eltern- zum Kindcontroller können Sie im Kindcontroller direkt auf Elterndaten zugreifen durch $scope
Wenn Sie ui-router verwenden, können Sie $stateParmas verwenden, um URL-Parameter wie id, name, key usw. zu übergeben

$broadcast ist auch eine gute Möglichkeit, Daten zwischen Controllern vom Eltern- zum Kindcontroller zu übertragen und $emit um Daten von Kind- zu Elterncontrollern zu übertragen

HTML

   Eingabe ist : {{FirstName}}

   Eingabe sollte auch hier sein: {{FirstName}}

JS

myApp.controller('FirstCtrl', function( $rootScope, Data ){
    $rootScope.$broadcast('myData', {'FirstName': 'Peter'})
});

myApp.controller('SecondCtrl', function( $rootScope, Data ){
    $rootScope.$on('myData', function(event, data) {
       $scope.FirstName = data;
       console.log(data); // Überprüfen Sie in der Konsole, wie die Daten eintreffen
    });
});

Verweisen Sie auf den angegebenen Link, um mehr über $broadcast zu erfahren

6voto

Oberdan Nunes Punkte 509

Ich habe eine Factory erstellt, die den gemeinsamen Bereich zwischen dem Muster des Routenpfads steuert, so dass Sie die gemeinsamen Daten beibehalten können, nur wenn Benutzer im gleichen Routen-Elternpfad navigieren.

.controller('CadastroController', ['$scope', 'RouteSharedScope',
    function($scope, routeSharedScope) {
      var customerScope = routeSharedScope.scopeFor('/Customer');
      //var indexScope = routeSharedScope.scopeFor('/');
    }
 ])

Wenn der Benutzer also zu einem anderen Routenpfad geht, zum Beispiel '/Support', werden die gemeinsamen Daten für den Pfad '/Customer' automatisch zerstört. Aber wenn der Benutzer stattdessen zu 'untergeordneten' Pfaden wie '/Customer/1' oder '/Customer/list' geht, wird der Scope nicht zerstört.

Sie können hier ein Beispiel sehen: http://plnkr.co/edit/OL8of9

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X