funciones entre ejemplos directivas controladores comunicacion javascript angularjs angularjs-controller

javascript - entre - funciones en angularjs



AngularJS: ¿Cómo puedo pasar variables entre los controladores? (15)

Tengo dos controladores angulares:

function Ctrl1($scope) { $scope.prop1 = "First"; } function Ctrl2($scope) { $scope.prop2 = "Second"; $scope.both = Ctrl1.prop1 + $scope.prop2; //This is what I would like to do ideally }

No puedo usar Ctrl1 dentro de Ctrl2 porque no está definido. Sin embargo si trato de pasarlo así ...

function Ctrl2($scope, Ctrl1) { $scope.prop2 = "Second"; $scope.both = Ctrl1.prop1 + $scope.prop2; //This is what I would like to do ideally }

Me sale un error. ¿Alguien sabe como hacer esto?

Obra

Ctrl2.prototype = new Ctrl1();

También falla.

NOTA: Estos controladores no están anidados uno dentro del otro.


¿No podría usted también hacer que la propiedad sea parte de los ámbitos padre?

$scope.$parent.property = somevalue;

No estoy diciendo que esté bien, pero funciona.


Además de $ rootScope y servicios, hay una solución alternativa limpia y fácil de ampliar angular para agregar los datos compartidos:

en los controladores:

angular.sharedProperties = angular.sharedProperties || angular.extend(the-properties-objects);

Estas propiedades pertenecen al objeto ''angular'', separado de los ámbitos, y pueden compartirse en ámbitos y servicios.

Tengo el beneficio de que no tiene que inyectar el objeto: ¡se puede acceder a ellos desde cualquier lugar inmediatamente después de su definición!


Ah, tener un poco de estas cosas nuevas como otra alternativa. Es almacenaje local, y trabaja donde trabaja anguloso. De nada. (Pero en realidad, gracias al chico)

https://github.com/gsklee/ngStorage

Defina sus valores predeterminados:

$scope.$storage = $localStorage.$default({ prop1: ''First'', prop2: ''Second'' });

Accede a los valores:

$scope.prop1 = $localStorage.prop1; $scope.prop2 = $localStorage.prop2;

Almacenar los valores

$localStorage.prop1 = $scope.prop1; $localStorage.prop2 = $scope.prop2;

Recuerde inyectar ngStorage en su aplicación y $ localStorage en su controlador.


El siguiente ejemplo muestra cómo pasar variables entre los controladores de hermanos y realizar una acción cuando el valor cambia.

Ejemplo de caso de uso: tiene un filtro en una barra lateral que cambia el contenido de otra vista.

angular.module(''myApp'', []) .factory(''MyService'', function() { // private var value = 0; // public return { getValue: function() { return value; }, setValue: function(val) { value = val; } }; }) .controller(''Ctrl1'', function($scope, $rootScope, MyService) { $scope.update = function() { MyService.setValue($scope.value); $rootScope.$broadcast(''increment-value-event''); }; }) .controller(''Ctrl2'', function($scope, MyService) { $scope.value = MyService.getValue(); $scope.$on(''increment-value-event'', function() { $scope.value = MyService.getValue(); }); });

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="myApp"> <h3>Controller 1 Scope</h3> <div ng-controller="Ctrl1"> <input type="text" ng-model="value"/> <button ng-click="update()">Update</button> </div> <hr> <h3>Controller 2 Scope</h3> <div ng-controller="Ctrl2"> Value: {{ value }} </div> </div>


Hay dos maneras de hacer esto

1) Utilizar el servicio get / set.

2) $scope.$emit(''key'', {data: value}); //to set the value $scope.$emit(''key'', {data: value}); //to set the value

$rootScope.$on(''key'', function (event, data) {}); // to get the value


La muestra anterior funcionó a la perfección. Acabo de hacer una modificación en caso de que necesite administrar varios valores. ¡Espero que esto ayude!

app.service(''sharedProperties'', function () { var hashtable = {}; return { setValue: function (key, value) { hashtable[key] = value; }, getValue: function (key) { return hashtable[key]; } } });


Me gusta ilustrar cosas simples con ejemplos simples :)

Aquí hay un ejemplo de Service muy simple:

angular.module(''toDo'',[]) .service(''dataService'', function() { // private variable var _dataObj = {}; // public API this.dataObj = _dataObj; }) .controller(''One'', function($scope, dataService) { $scope.data = dataService.dataObj; }) .controller(''Two'', function($scope, dataService) { $scope.data = dataService.dataObj; });

Y aquí el jsbin.

Y aquí hay un ejemplo de Factory muy simple:

angular.module(''toDo'',[]) .factory(''dataService'', function() { // private variable var _dataObj = {}; // public API return { dataObj: _dataObj }; }) .controller(''One'', function($scope, dataService) { $scope.data = dataService.dataObj; }) .controller(''Two'', function($scope, dataService) { $scope.data = dataService.dataObj; });

Y aquí el jsbin.

Si eso es demasiado simple, aquí hay un ejemplo más sofisticado.

También vea la respuesta aquí para comentarios de mejores prácticas relacionadas


Me gustaría contribuir a esta pregunta señalando que la forma recomendada de compartir datos entre controladores e incluso directivas es mediante el uso de servicios (fábricas) como ya se ha señalado, pero también me gustaría proporcionar una Trabajo práctico ejemplo de cómo se debe hacer.

Aquí está el plunker de trabajo: http://plnkr.co/edit/Q1VdKJP2tpvqqJL1LF6m?p=info

Primero, crea tu servicio , que tendrá tus datos compartidos :

app.factory(''SharedService'', function() { return { sharedObject: { value: '''', value2: '''' } }; });

Luego, simplemente inyecte en sus controladores y tome los datos compartidos de su alcance:

app.controller(''FirstCtrl'', function($scope, SharedService) { $scope.model = SharedService.sharedObject; }); app.controller(''SecondCtrl'', function($scope, SharedService) { $scope.model = SharedService.sharedObject; }); app.controller(''MainCtrl'', function($scope, SharedService) { $scope.model = SharedService.sharedObject; });

También puedes hacer eso para tus directivas , funciona de la misma manera:

app.directive(''myDirective'',[''SharedService'', function(SharedService){ return{ restrict: ''E'', link: function(scope){ scope.model = SharedService.sharedObject; }, template: ''<div><input type="text" ng-model="model.value"/></div>'' } }]);

Espero que esta respuesta práctica y limpia pueda ser útil para alguien.


Podrías hacer eso con servicios o fábricas. Son esencialmente lo mismo aparte de algunas diferencias fundamentales. Encontré que esta explicación en thinkster.io es la más fácil de seguir. Sencillo, al punto y efectivo.


Segundo enfoque:

angular.module(''myApp'', []) .controller(''Ctrl1'', [''$scope'', function($scope) { $scope.prop1 = "First"; $scope.clickFunction = function() { $scope.$broadcast(''update_Ctrl2_controller'', $scope.prop1); }; } ]) .controller(''Ctrl2'', [''$scope'', function($scope) { $scope.prop2 = "Second"; $scope.$on("update_Ctrl2_controller", function(event, prop) { $scope.prop = prop; $scope.both = prop + $scope.prop2; }); } ])

HTML:

<div ng-controller="Ctrl2"> <p>{{both}}</p> </div> <button ng-click="clickFunction()">Click</button>

Para más detalles ver plunker:

http://plnkr.co/edit/cKVsPcfs1A1Wwlud2jtO?p=preview


Si no quieres hacer un servicio, puedes hacerlo de esta manera.

var scope = angular.element("#another ctrl scope element id.").scope(); scope.plean_assign = some_value;


Tiendo a usar valores, me alegro de que alguien discuta por qué esto es una mala idea.

var myApp = angular.module(''myApp'', []); myApp.value(''sharedProperties'', {}); //set to empty object -

Luego inyecte el valor según un servicio.

Establecer en ctrl1:

myApp.controller(''ctrl1'', function DemoController(sharedProperties) { sharedProperties.carModel = "Galaxy"; sharedProperties.carMake = "Ford"; });

y acceso desde ctrl2:

myApp.controller(''ctrl2'', function DemoController(sharedProperties) { this.car = sharedProperties.carModel + sharedProperties.carMake; });


Una forma de compartir variables entre varios controladores es crear un servicio e inyectarlo en cualquier controlador en el que desee usarlo.

Ejemplo de servicio simple:

angular.module(''myApp'', []) .service(''sharedProperties'', function () { var property = ''First''; return { getProperty: function () { return property; }, setProperty: function(value) { property = value; } }; });

Utilizando el servicio en un controlador:

function Ctrl2($scope, sharedProperties) { $scope.prop2 = "Second"; $scope.both = sharedProperties.getProperty() + $scope.prop2; }

Esto se describe muy bien en este blog (Lección 2 y en particular).

Descubrí que si desea enlazar a estas propiedades a través de múltiples controladores, funciona mejor si se enlaza a la propiedad de un objeto en lugar de a un tipo primitivo (booleano, cadena, número) para conservar la referencia enlazada.

Ejemplo: var property = { Property1: ''First'' }; en lugar de var property = ''First''; .

ACTUALIZACIÓN: (con suerte) para aclarar las cosas aquí hay un violín que muestra un ejemplo de:

  • Enlace a copias estáticas del valor compartido (en myController1)
    • Enlace a una primitiva (cadena)
    • Enlace a la propiedad de un objeto (guardado en una variable de alcance)
  • Enlace a valores compartidos que actualizan la interfaz de usuario a medida que se actualizan los valores (en myController2)
    • Enlace a una función que devuelve una primitiva (cadena)
    • Vinculación a la propiedad del objeto.
    • Enlace bidireccional a la propiedad de un objeto.

--- Sé que esta respuesta no es para esta pregunta, pero quiero que las personas que lean esta pregunta y quieran manejar Servicios como las Fábricas para evitar problemas al hacerlo ----

Para esto necesitarás usar un Servicio o una Fábrica.

Los servicios son la MEJOR PRÁCTICA para compartir datos entre controladores no anidados.

Una muy buena anotación sobre este tema sobre el intercambio de datos es cómo declarar objetos. Tuve mala suerte porque caí en una trampa de AngularJS antes de leer sobre eso, y me sentí muy frustrado. Así que déjame ayudarte a evitar este problema.

Leí en el "ng-book: el libro completo en AngularJS" que los modelos ng de AngularJS que se crean en los controladores como datos desnudos están MAL.

Un elemento $ scope debería crearse así:

angular.module(''myApp'', []) .controller(''SomeCtrl'', function($scope) { // best practice, always use a model $scope.someModel = { someValue: ''hello computer'' });

Y no así:

angular.module(''myApp'', []) .controller(''SomeCtrl'', function($scope) { // anti-pattern, bare value $scope.someBareValue = ''hello computer''; }; });

Esto se debe a que se recomienda (MEJOR PRÁCTICA) que el DOM (documento html) contenga las llamadas como

<div ng-model="someModel.someValue"></div> //NOTICE THE DOT.

Esto es muy útil para los controladores anidados si desea que su controlador secundario pueda cambiar un objeto desde el controlador principal ...

Pero en su caso, no desea que haya ámbitos anidados, pero hay un aspecto similar para obtener objetos de los servicios a los controladores.

Digamos que tiene su servicio ''Factory'' y en el espacio de retorno hay un objectA que contiene objectB que contiene objectC.

Si desde su controlador desea obtener el objectC en su alcance, es un error decir:

$scope.neededObjectInController = Factory.objectA.objectB.objectC;

Eso no funcionará ... En vez de eso, usa solo un punto.

$scope.neededObjectInController = Factory.ObjectA;

Luego, en el DOM puede llamar a objectC desde objectA. Esta es una buena práctica relacionada con las fábricas y, lo más importante, ayudará a evitar errores inesperados y no detectables.


Solución sin crear Servicio, usando $ rootScope:

Para compartir propiedades entre los controladores de aplicaciones, puede usar Angular $ rootScope. Esta es otra opción para compartir datos, poniéndolos para que la gente sepa sobre ellos.

La forma preferida de compartir alguna funcionalidad entre los Controladores es Servicios, para leer o cambiar una propiedad global que puede usar $ rootscope.

var app = angular.module(''mymodule'',[]); app.controller(''Ctrl1'', [''$scope'',''$rootScope'', function($scope, $rootScope) { $rootScope.showBanner = true; }]); app.controller(''Ctrl2'', [''$scope'',''$rootScope'', function($scope, $rootScope) { $rootScope.showBanner = false; }]);

Usando $ rootScope en una plantilla (propiedades de acceso con $ root):

<div ng-controller="Ctrl1"> <div class="banner" ng-show="$root.showBanner"> </div> </div>