una pasar parametros funcion entre datos controladores conectar comunicar comunicacion componentes compartir javascript angularjs

javascript - funcion - pasar parametros entre controladores angular 2



Compartir datos entre los controladores AngularJS (10)

Estoy tratando de compartir datos entre los controladores. El caso de uso es un formulario de varios pasos, los datos ingresados ​​en una entrada se usan más tarde en múltiples ubicaciones de visualización fuera del controlador original. Código abajo y en jsfiddle aquí .

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

Cualquier ayuda es muy apreciada.


La solución más simple:

He utilizado un servicio AngularJS .

Paso 1: He creado un servicio AngularJS llamado SharedDataService.

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

Paso 2: crea dos controladores y utiliza el servicio creado anteriormente.

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

Paso 3: Simplemente use los controladores creados en la vista.

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

Para ver la solución de trabajo a este problema, presione el siguiente enlace

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

archivo .html:

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


Existen múltiples formas de compartir datos entre los controladores.

  • Servicios angulares
  • $ broadcast, $ emitir método
  • Comunicación padre a hijo controlador
  • $ rootscope

Como sabemos, $rootscope no es una forma preferible para la transferencia de datos o la comunicación, ya que es un ámbito global que está disponible para toda la aplicación.

Para compartir datos entre los controladores Angular Js, los servicios angulares son las mejores prácticas, por ejemplo .factory , .service
Para reference

En caso de transferencia de datos del controlador principal al secundario, puede acceder directamente a los datos principales del controlador secundario a través de $scope
Si está utilizando ui-router , puede usar $stateParmas para pasar parámetros de URL como id , name , key , etc.

$broadcast también es una buena forma de transferir datos entre controladores de padres a hijos y $emit para transferir datos de niños a controladores principales

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

Consulte el link dado para saber más sobre $broadcast


Hay muchas maneras de compartir los datos entre los controladores.

  1. usando servicios
  2. utilizando los servicios de $ state.go
  3. usando parques estatales
  4. usando rootscope

Explicación de cada método:

  1. No voy a explicar como ya lo explicó alguien.

  2. usando $state.go

    $state.go(''book.name'', {Name: ''XYZ''}); // then get parameter out of URL $state.params.Name;

  3. $stateparam funciona de manera similar a $state.go , usted lo pasa como un objeto desde el controlador del remitente y lo recoge en el controlador del receptor utilizando stateparam

  4. usando $rootscope

    (a) envío de datos del niño al controlador principal

    $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) envío de datos de padre a controlador hijo

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


Hay otra forma sin usar $ watch, usando 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; });


Hay varias formas de hacer esto.

  1. Eventos - ya explicados bien.

  2. enrutador ui - explicado anteriormente.

  3. Servicio - con el método de actualización mostrado arriba
  4. MALO - Observando cambios.
  5. Otro enfoque padre-hijo en lugar de emitir y 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(); } } });


He creado una fábrica que controla el alcance compartido entre el patrón de la ruta de acceso, por lo que puede mantener los datos compartidos justo cuando los usuarios navegan en la ruta principal de la misma ruta.

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

Por lo tanto, si el usuario va a otra ruta, por ejemplo ''/ Soporte'', los datos compartidos para la ruta ''/ Cliente'' se destruirán automáticamente. Pero, si en lugar de esto, el usuario va a las rutas ''secundarias'', como ''/ Customer / 1'' o ''/ Customer / list'', el alcance no se destruirá.

Puede ver un ejemplo aquí: http://plnkr.co/edit/OL8of9


No estoy seguro de dónde recogí este patrón, pero para compartir datos entre los controladores y reducir $ rootScope y $ scope esto funciona muy bien. Es una reminiscencia de una replicación de datos donde tienes editores y suscriptores. Espero eso ayude.

El servicio:

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

El controlador que está obteniendo los nuevos datos, que es el editor, haría algo como esto ...

var someData = yourDataService.getSomeData(); sharedDataEventHub.changeData(someData);

El Controlador que también utiliza estos nuevos datos, que se llama el Suscriptor, haría algo como esto ...

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

Esto funcionará para cualquier escenario. Entonces, cuando el controlador primario se inicializa y obtiene datos, llamará al método changeData que luego lo difundirá a todos los suscriptores de esos datos. Esto reduce el acoplamiento de nuestros controladores entre sí.


Prefiero no usar $watch para esto. En lugar de asignar todo el servicio al alcance de un controlador, puede asignar solo los datos.

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>

Alternativamente, puede actualizar los datos del servicio con un método directo.

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


Solo hazlo simple (probado con v1.3.15):

<article ng-controller="ctrl1 as c1"> <label>Change name here:</label> <input ng-model="c1.sData.name" /> <h1>Control 1: {{c1.sData.name}}, {{c1.sData.age}}</h1> </article> <article ng-controller="ctrl2 as c2"> <label>Change age here:</label> <input ng-model="c2.sData.age" /> <h1>Control 2: {{c2.sData.name}}, {{c2.sData.age}}</h1> </article> <script> var app = angular.module("MyApp", []); var dummy = {name: "Joe", age: 25}; app.controller("ctrl1", function () { this.sData = dummy; }); app.controller("ctrl2", function () { this.sData = dummy; }); </script>


Una solución simple es que su fábrica devuelva un objeto y permita que sus controladores trabajen con una referencia al mismo objeto:

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>

Demostración: http://jsfiddle.net/HEdJF/

Cuando las aplicaciones se vuelven más grandes, más complejas y más difíciles de probar, es posible que no desee exponer todo el objeto de la fábrica de esta manera, sino que se le otorgue acceso limitado, por ejemplo, a través de captadores y configuradores:

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

Con este enfoque, depende de los controladores consumidores actualizar la fábrica con nuevos valores y observar los cambios para obtenerlos:

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>

Demostración: http://jsfiddle.net/27mk1n1o/