Gegevens delen tussen AngularJS-controllers

Ik probeer gegevens te delen tussen controllers. Use-case is een formulier dat uit meerdere stappen bestaat, gegevens die in één invoer zijn ingevoerd, worden later gebruikt op meerdere weergavelocaties buiten de oorspronkelijke controller. Code hieronder en in jsfiddle hier.

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;
});

Alle hulp wordt zeer op prijs gesteld.


Antwoord 1, autoriteit 100%

Een eenvoudige oplossing is om uw fabriek een object te laten retourneren en uw controllers te laten werken met een verwijzing naar hetzelfde object:

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/

Als applicaties groter, complexer en moeilijker te testen worden, wil je misschien niet het hele object vanuit de fabriek op deze manier blootleggen, maar in plaats daarvan beperkte toegang geven, bijvoorbeeld via getters en setters:

myApp.factory('Data', function () {
    var data = {
        FirstName: ''
    };
    return {
        getFirstName: function () {
            return data.FirstName;
        },
        setFirstName: function (firstName) {
            data.FirstName = firstName;
        }
    };
});

Bij deze benadering is het aan de verbruikende controllers om de fabriek bij te werken met nieuwe waarden en te letten op veranderingen om deze te verkrijgen:

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/


Antwoord 2, autoriteit 15%

Ik gebruik hiervoor liever geen $watch. In plaats van de hele service toe te wijzen aan het bereik van een controller, kunt u alleen de gegevens toewijzen.

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>

Als alternatief kunt u de servicegegevens bijwerken met een directe methode.

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);
   }
});

Antwoord 3, autoriteit 2%

Er zijn veel manieren waarop u de gegevens tussen controllers kunt delen

  1. services gebruiken
  2. $state.go-services gebruiken
  3. stateparams gebruiken
  4. rootscope gebruiken

Uitleg van elke methode:

  1. Ik ga het niet uitleggen omdat het al door iemand is uitgelegd

  2. met behulp van $state.go

     $state.go('book.name', {Name: 'XYZ'}); 
      // then get parameter out of URL
      $state.params.Name;
    
  3. $stateparamwerkt op dezelfde manier als $state.go, je geeft het door als object van de zendercontroller en verzamelt in de ontvangercontroller met behulp van stateparam

  4. met behulp van $rootscope

    (a) gegevens verzenden van kind-naar-ouder-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) gegevens verzenden van ouder naar kind-controller

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

Antwoord 4

Ik heb een fabriek gemaakt die het gedeelde bereik tussen het patroon van het routepad beheert, zodat u de gedeelde gegevens kunt behouden net wanneer gebruikers in hetzelfde bovenliggende routepad navigeren.

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

Dus als de gebruiker naar een ander routepad gaat, bijvoorbeeld ‘/Support’, worden de gedeelde gegevens voor pad ‘/Klant’ automatisch vernietigd. Maar als de gebruiker in plaats daarvan naar ‘onderliggende’ paden gaat, zoals ‘/Customer/1’ of ‘/Customer/list’, wordt het bereik niet vernietigd.

Je kunt hier een voorbeeld bekijken: http://plnkr.co/edit/OL8of9


Antwoord 5

Er zijn meerdere manieren om gegevens tussen controllers te delen

  • Hoekige diensten
  • $broadcast, $emit-methode
  • communicatie tussen ouder en kind
  • $rootscope

Zoals we weten is $rootscopeniet de voorkeursmethode voor gegevensoverdracht of communicatie, omdat het een globale scope is die beschikbaar is voor de hele applicatie

Voor het delen van gegevens tussen Angular Js-controllers Angular-services zijn best practices, bijvoorbeeld. .factory, .service
Voor referentie

In geval van gegevensoverdracht van ouder naar kind-controller heeft u rechtstreeks toegang tot oudergegevens in kind-controller via $scope
Als u ui-routergebruikt, kunt u $stateParmasgebruiken om url-parameters zoals id, name, door te geven, key, enz.

$broadcastis ook een goede manier om gegevens tussen controllers van ouder naar kind over te dragen en $emitom gegevens over te dragen van kind naar oudercontroller

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
    });
});

Raadpleeg de gegeven linkvoor meer informatie over $broadcast


Antwoord 6

Eenvoudigste oplossing:

Ik heb een AngularJS-servicegebruikt.

Stap1:ik heb een AngularJS-service gemaakt met de naam SharedDataService.

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

Stap2:Maak twee controllers en gebruik de hierboven gemaakte service.

//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;
   }]);

Stap3:gebruik gewoon de gemaakte controllers in de weergave.

<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>

Klik op de onderstaande link om een ​​werkende oplossing voor dit probleem te zien

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

.html-bestand:

<!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>

Antwoord 7

Er is een andere manier zonder $watch te gebruiken, met angular.copy:

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;
});

Antwoord 8

Er zijn meerdere manieren om dit te doen.

  1. Evenementen – al goed uitgelegd.

  2. ui router – hierboven uitgelegd.

  3. Service – met updatemethode hierboven weergegeven
  4. SLECHT– Let op veranderingen.
  5. Een andere ouder-kindbenadering in plaats van uitzendenen uitzending

*

<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();
        }
    }
});

Other episodes