Para Borja
En la primera entrada de esta serie expliqué cómo comunicar dos controladores que están activos al mismo tiempo mediante $emit, $broadcast y $on. En esta, veremos cómo pasar datos entre los controladores aunque se carguen en momentos distintos.
Doy por sentado que conocemos ui-router, que amplía en gran medida el sistema de rutas de Angular mediante la implementación de estados. Si no es así, es recomendable que leas antes esta entrada: angular para grandes aplicaciones (1).
Mediante params.
La manera más sencilla de compartir datos entre los controladores es añadiendo una clave en la definición de los estados denominada params y ahí definimos un objeto con los pares clave-valor que vamos a ir intercambiando, en los cuales podemos definir un valor por defecto, que en este ejemplo es null.
app.js
angular.module('demoScopes', [
'ngRoute',
'ui.router'
])
.config(function($stateProvider, $urlRouterProvider) {
/* Definimos un estado default */
$urlRouterProvider.otherwise("/estadoUno");
/* Preparamos el mapa de rutas / estados */
$stateProvider
.state('estadoUno', {
url: "/estadoUno",
templateUrl: "views/main.html",
controller: "MainCtrl",
params: {data: null}
})
.state('estadoDos', {
url: "/estadoDos",
templateUrl: "views/secondary.html",
controller: "SecondaryCtrl",
params: {data: null}
});
});
Y ya en los controladores solo tenemos que definir ese valor cuando cambiamos de estado mediante $state.go.
angular.module('demoScopes')
.controller('SecondaryCtrl', function ($scope, $state) {
/* Función que por ejemplo se llama con un ng-click desde la vista */
$scope.setEstado = function() {
$state.go('estadoUno', {data: "Awesome"});
}
});
Mediante una factoría
La manera anterior es eficaz, pero también podemos resolver la comunicación entre controladores mediante el uso de una factoría intermedia, pues recordemos que los servicios y las factorías son singletons, esto es, solo se instancian una vez durante todo el ciclo de vida de la aplicación. Así, solo tenemos que crear una factoría parecida a esta:
angular.module('demoScopes')
.factory("storage", function($log) {
var module = {};
/* Creamos el objeto donde iremos almacenando las cosas */
module.storage = {};
/* Un método para guardar las cosas, que recibe dos parámetros, el primero para la clave y el segundo para el valor */
module.saveData = function(key, value) {
this.storage[key] = value;
};
/* Otro para recuperar los datos */
module.getData = function(key) {
var temp = ( this.storage.hasOwnProperty(key) ) ? this.storage[key] : false;
return temp;
};
return module;
});
Y ya podemos usarlo a conveniencia desde los controladores.
storage.saveData("foo", "bar");
storage.getData("foo");