it-swarm.com.de

Teilen Sie Daten zwischen AngularJS-Controllern

Ich versuche, Daten zwischen Controllern auszutauschen. Der Anwendungsfall ist ein mehrstufiges Formular. Daten, die in einem Eingang eingegeben wurden, werden später an mehreren Anzeigestellen außerhalb des ursprünglichen Controllers verwendet. Code unten und in hier jsfiddle .

HTML

<div ng-controller="FirstCtrl">
    <input type="text" ng-model="FirstName"><!-- Input entered here -->
    <br>Input is : <strong>{{FirstName}}</strong><!-- Successfully updates here -->
</div>

<hr>

<div ng-controller="SecondCtrl">
    Input should also be here: {{FirstName}}<!-- How do I automatically updated it here? -->
</div>

JS

// declare the app with no dependencies
var myApp = angular.module('myApp', []);

// make a factory to share data between controllers
myApp.factory('Data', function(){
    // I know this doesn't work, but what will?
    var FirstName = '';
    return FirstName;
});

// Step 1 Controller
myApp.controller('FirstCtrl', function( $scope, Data ){

});

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

Jede Hilfe wird sehr geschätzt.

353
johnkeese

Eine einfache Lösung besteht darin, dass Ihre Fabrik ein Objekt zurücksendet und Ihre Steuerungen mit einem Verweis auf dasselbe Objekt arbeiten lässt:

JS:

// declare the app with no dependencies
var myApp = angular.module('myApp', []);

// Create the factory that share the Fact
myApp.factory('Fact', function(){
  return { Field: '' };
});

// Two controllers sharing an object that has a string in it
myApp.controller('FirstCtrl', function( $scope, Fact ){
  $scope.Alpha = Fact;
});

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

HTML:

<div ng-controller="FirstCtrl">
    <input type="text" ng-model="Alpha.Field">
    First {{Alpha.Field}}
</div>

<div ng-controller="SecondCtrl">
<input type="text" ng-model="Beta.Field">
    Second {{Beta.Field}}
</div>

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

Wenn Anwendungen größer, komplexer und schwieriger zu testen sind, möchten Sie möglicherweise nicht das gesamte Objekt ab Werk auf diese Weise verfügbar machen, sondern nur eingeschränkten Zugriff gewähren, z. B. über Getter und Setter:

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

    var data = {
        FirstName: ''
    };

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

Bei diesem Ansatz ist es Sache der konsumierenden Steuerungen, die Fabrik mit neuen Werten zu aktualisieren und auf Änderungen zu achten, um diese 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:

<div ng-controller="FirstCtrl">
  <input type="text" ng-model="firstName">
  <br>Input is : <strong>{{firstName}}</strong>
</div>
<hr>
<div ng-controller="SecondCtrl">
  Input should also be here: {{firstName}}
</div>

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

470
tasseKATT

Ich bevorzuge es, $watch dafür nicht zu verwenden. Anstatt den gesamten Dienst dem 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: ''
    }
    // Other methods or objects can go here
  };
});

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

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

HTML:

<div ng-controller="FirstCtrl">
  <input type="text" ng-model="data.firstName">
  <br>Input is : <strong>{{data.firstName}}</strong>
</div>
<hr>
<div ng-controller="SecondCtrl">
  Input should also be here: {{data.firstName}}
</div>

Alternativ können Sie die Servicedaten auch direkt aktualisieren.

JS:

// A new factory with an update method
myApp.factory('MyService', function(){
  return {
    data: {
      firstName: '',
      lastName: ''
    },
    update: function(first, last) {
      // Improve this method as needed
      this.data.firstName = first;
      this.data.lastName = last;
    }
  };
});

// Your controller can use the service's update method
myApp.controller('SecondCtrl', function($scope, MyService){
   $scope.data = MyService.data;

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

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

  1. nutzung von Diensten
  2. mit $ state.go-Diensten
  3. mit stateparams
  4. mit rootscope

Erklärung der einzelnen Methoden:

  1. Ich werde nicht erklären, wie es schon jemand erklärt hat

  2. mit $state.go

      $state.go('book.name', {Name: 'XYZ'}); 
    
      // then get parameter out of URL
      $state.params.Name;
    
  3. $stateparam funktioniert ähnlich wie $state.go, Sie übergeben es als Objekt vom Sender-Controller und sammeln es im Empfänger-Controller mit stateparam

  4. mit $rootscope

    (a) Senden von Daten vom untergeordneten zum übergeordneten Controller

      $scope.Save(Obj,function(data) {
          $scope.$emit('savedata',data); 
          //pass the data as the second parameter
      });
    
      $scope.$on('savedata',function(event,data) {
          //receive the data as second parameter
      }); 
    

    (b) Senden von Daten vom übergeordneten zum untergeordneten Controller

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

Ich habe eine Factory erstellt, die den gemeinsam genutzten Bereich zwischen den Routenpfadmustern steuert, sodass Sie die gemeinsam genutzten Daten nur dann verwalten können, wenn Benutzer auf demselben übergeordneten Routenpfad 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 wechselt, z. B. '/ Support', werden die freigegebenen Daten für den Pfad '/ Customer' automatisch gelöscht. Wenn der Benutzer jedoch stattdessen auf "untergeordnete" Pfade wie "/ Kunde/1" oder "/ Kunde/Liste" wechselt, wird der Gültigkeitsbereich nicht zerstört.

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

6
Oberdan Nunes

Es gibt mehrere Möglichkeiten, Daten zwischen Controllern auszutauschen

  • Angular Dienstleistungen
  • $ broadcast, $ emit-Methode
  • Parent-to-Child-Controller-Kommunikation
  • $ rootscope

Wie wir wissen, ist $rootscope keine bevorzugte Methode für die Datenübertragung oder -kommunikation, da es sich um einen globalen Bereich handelt, der für die gesamte Anwendung verfügbar ist

Für den Datenaustausch zwischen Angular Js Controllern Angular sind Dienste bewährte Methoden, z. .factory, .service
Zu Referenz

Bei der Datenübertragung vom übergeordneten zum untergeordneten Controller können Sie über $scope direkt auf die übergeordneten Daten im untergeordneten Controller zugreifen.
Wenn Sie ui-router verwenden, können Sie $stateParmas verwenden, um URL-Parameter wie id, name, key usw

$broadcast ist auch eine gute Methode zum Übertragen von Daten zwischen Steuerungen von übergeordneten zu untergeordneten Steuerungen und $emit zum Übertragen von Daten von untergeordneten zu übergeordneten Steuerungen

HTML

<div ng-controller="FirstCtrl">
   <input type="text" ng-model="FirstName">
   <br>Input is : <strong>{{FirstName}}</strong>
</div>

<hr>

<div ng-controller="SecondCtrl">
   Input should also be here: {{FirstName}}
</div>

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); // Check in console how data is coming
    });
});

Siehe angegeben Link um mehr über $broadcast zu erfahren

4
ojus kulkarni

Einfachste Lösung:

Ich habe einen AngularJS-Dienst verwendet.

Schritt 1: Ich habe einen AngularJS-Dienst mit dem Namen SharedDataService erstellt.

myApp.service('SharedDataService', function () {
     var Person = {
        name: ''

    };
    return Person;
});

Schritt 2: Erstellen Sie zwei Controller und verwenden Sie den oben erstellten Dienst.

//First Controller
myApp.controller("FirstCtrl", ['$scope', 'SharedDataService',
   function ($scope, SharedDataService) {
   $scope.Person = SharedDataService;
   }]);

//Second Controller
myApp.controller("SecondCtrl", ['$scope', 'SharedDataService',
   function ($scope, SharedDataService) {
   $scope.Person = SharedDataService;
   }]);

Schritt 3: Verwenden Sie einfach die erstellten Controller in der Ansicht.

<body ng-app="myApp">

<div ng-controller="FirstCtrl">
<input type="text" ng-model="Person.name">
<br>Input is : <strong>{{Person.name}}</strong>
</div>

<hr>

<div ng-controller="SecondCtrl">
Input should also be here: {{Person.name}}
</div>

</body>

Um eine funktionierende Lösung für dieses Problem zu finden, klicken Sie bitte auf den folgenden Link

https://codepen.io/wins/pen/bmoYLr

. html-Datei:

<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>

<body ng-app="myApp">

  <div ng-controller="FirstCtrl">
    <input type="text" ng-model="Person.name">
    <br>Input is : <strong>{{Person.name}}</strong>
   </div>

<hr>

  <div ng-controller="SecondCtrl">
    Input should also be here: {{Person.name}}
  </div>

//Script starts from here

<script>

var myApp = angular.module("myApp",[]);
//create SharedDataService
myApp.service('SharedDataService', function () {
     var Person = {
        name: ''

    };
    return Person;
});

//First Controller
myApp.controller("FirstCtrl", ['$scope', 'SharedDataService',
    function ($scope, SharedDataService) {
    $scope.Person = SharedDataService;
    }]);

//Second Controller
myApp.controller("SecondCtrl", ['$scope', 'SharedDataService',
    function ($scope, SharedDataService) {
    $scope.Person = SharedDataService;
}]);

</script>


</body>
</html>
2
wins999

Es gibt eine andere Möglichkeit, ohne $ watch zu verwenden:

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

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

    var service = {
        FirstName: '',
        setFirstName: function(name) {
            // this is the trick to sync the data
            // so no need for a $watch function
            // call this from anywhere when you need to update FirstName
            angular.copy(name, service.FirstName); 
        }
    };
    return service;
});


// Step 1 Controller
myApp.controller('FirstCtrl', function( $scope, Data ){

});

// Step 2 Controller
myApp.controller('SecondCtrl', function( $scope, Data ){
    $scope.FirstName = Data.FirstName;
});
1
Hinrich

Hierfür gibt es mehrere Möglichkeiten.

  1. Ereignisse - bereits gut erklärt.

  2. ui Router - oben erklärt.

  3. Service - mit der oben angezeigten Aktualisierungsmethode
  4. BAD - Auf Änderungen achten.
  5. Ein anderer Eltern-Kind-Ansatz als emittieren und brodcast -

*

<superhero flight speed strength> Superman is here! </superhero>
<superhero speed> Flash is here! </superhero>

*

app.directive('superhero', function(){
    return {
        restrict: 'E',
        scope:{}, // IMPORTANT - to make the scope isolated else we will pollute it in case of a multiple components.
        controller: function($scope){
            $scope.abilities = [];
            this.addStrength = function(){
                $scope.abilities.Push("strength");
            }
            this.addSpeed = function(){
                $scope.abilities.Push("speed");
            }
            this.addFlight = function(){
                $scope.abilities.Push("flight");
            }
        },
        link: function(scope, element, attrs){
            element.addClass('button');
            element.on('mouseenter', function(){
               console.log(scope.abilities);
            })
        }
    }
});
app.directive('strength', function(){
    return{
        require:'superhero',
        link: function(scope, element, attrs, superHeroCtrl){
            superHeroCtrl.addStrength();
        }
    }
});
app.directive('speed', function(){
    return{
        require:'superhero',
        link: function(scope, element, attrs, superHeroCtrl){
            superHeroCtrl.addSpeed();
        }
    }
});
app.directive('flight', function(){
    return{
        require:'superhero',
        link: function(scope, element, attrs, superHeroCtrl){
            superHeroCtrl.addFlight();
        }
    }
});
1
user2756335

Ich bin mir nicht sicher, wo ich dieses Muster aufgenommen habe, aber um Daten zwischen Controllern auszutauschen und $ rootScope und $ scope zu reduzieren, funktioniert das großartig. Es erinnert an eine Datenreplikation, bei der Sie Herausgeber und Abonnenten haben. Ich hoffe es hilft.

Der Service:

(function(app) {
    "use strict";
    app.factory("sharedDataEventHub", sharedDataEventHub);

    sharedDataEventHub.$inject = ["$rootScope"];

    function sharedDataEventHub($rootScope) {
        var DATA_CHANGE = "DATA_CHANGE_EVENT";
        var service = {
            changeData: changeData,
            onChangeData: onChangeData
        };
        return service;

        function changeData(obj) {
            $rootScope.$broadcast(DATA_CHANGE, obj);
        }

        function onChangeData($scope, handler) {
            $scope.$on(DATA_CHANGE, function(event, obj) {
                handler(obj);
            });
        }
    }
}(app));

Der Controller, der die neuen Daten erhält, also der Publisher, würde so etwas tun.

var someData = yourDataService.getSomeData();

sharedDataEventHub.changeData(someData);

Der Controller, der auch diese neuen Daten verwendet, die als Abonnent bezeichnet werden, würde so etwas tun ...

sharedDataEventHub.onChangeData($scope, function(data) {
    vm.localData.Property1 = data.Property1;
    vm.localData.Property2 = data.Property2;
});

Dies funktioniert in jedem Szenario. Wenn der primäre Controller initialisiert wird und Daten erhält, ruft er die changeData-Methode auf, die diese dann an alle Abonnenten dieser Daten sendet. Dies reduziert die Kopplung unserer Regler untereinander.

0
ewahner