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.

5voto

wins999 Punkte 1452

Einfachste Lösung:

Ich habe einen AngularJS-Service verwendet.

Schritt 1: Ich habe einen AngularJS-Service namens SharedDataService erstellt.

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

    };
    return Person;
});

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

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

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

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

Eingabe ist : {{Person.name}}

Eingabe sollte auch hier sein: {{Person.name}}

Um die Lösung für dieses Problem in Aktion zu sehen, klicken Sie bitte auf den unten stehenden Link

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

.html-Datei:

    Eingabe ist : {{Person.name}}

    Eingabe sollte auch hier sein: {{Person.name}}

//Das Skript beginnt hier

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

    };
    return Person;
});

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

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

1voto

Hinrich Punkte 12847

Es gibt eine andere Möglichkeit, ohne $watch zu verwenden, nämlich mit angular.copy:

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

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

    var service = {
        FirstName: '',
        setFirstName: function(name) {
            // das ist der Trick, um die Daten zu synchronisieren
            // also kein Bedarf für eine $watch Funktion
            // rufen Sie dies von überall auf, wenn Sie den Vornamen aktualisieren müssen
            angular.copy(name, service.FirstName); 
        }
    };
    return service;
});

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

});

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

1voto

user2756335 Punkte 119

Es gibt mehrere Möglichkeiten, dies zu tun.

  1. Ereignisse - bereits gut erklärt.

  2. UI-Router - oben erklärt.

  3. Service - mit oben angezeigter Update-Methode

  4. SCHLECHT - Beobachten von Änderungen.

  5. Ein weiterer Eltern-Kind-Ansatz anstelle von emit und broadcast -

*

 Superman ist hier! 
 Flash ist hier! 

*

app.directive('superhero', function(){
    return {
        restrict: 'E',
        scope:{}, // WICHTIG - um den Scope isoliert zu machen, sonst würden wir ihn bei mehreren Komponenten verunreinigen.
        controller: function($scope){
            $scope.abilities = [];
            this.addStrength = function(){
                $scope.abilities.push("Stärke");
            }
            this.addSpeed = function(){
                $scope.abilities.push("Geschwindigkeit");
            }
            this.addFlight = function(){
                $scope.abilities.push("Flug");
            }
        },
        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();
        }
    }
});

0voto

ewahner Punkte 1149

Nicht sicher, wo ich dieses Muster aufgegriffen habe, aber für den Datenaustausch zwischen Controllern und zur Reduzierung des $rootScope und $scope funktioniert dies großartig. Es erinnert an eine Datenreplikation, bei der es Publisher und Abonnenten gibt. 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, würde als Publisher etwas Ähnliches tun..

var someData = yourDataService.getSomeData();

sharedDataEventHub.changeData(someData);

Der Controller, der auch diese neuen Daten verwendet, der als Abonnent bezeichnet wird, würde etwas Ähnliches tun...

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

Dies funktioniert für jedes Szenario. Wenn also der Hauptcontroller initialisiert wird und Daten erhält, würde er die changeData-Methode aufrufen, die dann diese an alle Abonnenten dieser Daten übertragen würde. Dies reduziert die Kopplung unserer Controller untereinander.

0voto

Wie von @MaNn in einem der Kommentare der angenommenen Antworten darauf hingewiesen wurde, funktioniert die Lösung nicht, wenn die Seite neu geladen wird.

Die Lösung dafür besteht darin, localStorage oder sessionStorage für die vorübergehende Speicherung der Daten zu verwenden, die Sie über Controller hinweg teilen möchten.

  1. Entweder Sie erstellen einen sessionService, dessen GET- und SET-Methode die Daten verschlüsselt und entschlüsselt und die Daten entweder aus localStorage oder sessionStorage liest. Jetzt verwenden Sie diesen Service direkt, um die Daten im Speicher über jeden gewünschten Controller oder Service zu lesen und zu schreiben. Dies ist ein offener und einfacher Ansatz.
  2. Sonst erstellen Sie einen DataSharing-Service und verwenden localStorage darin - sodass, wenn die Seite neu geladen wird, der Service versucht, den Speicher zu überprüfen und über die Getters und Setters, die Sie in dieser Service-Datei öffentlich oder privat gemacht haben, zurückzumelden.

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