Foro

Obtener el valor de 3 select de diferentes controladores en un controlador principal

0
Que tal, recientemente empece con angular
Tengo una duda en lo siguiente:
Hice 2 archivos en plunker,  en el siguiente link para un ejemplo mas claro

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

Los select
<body ng-app="MyForm">

	<div id="container" ng-controller="mainController">

<!-- comment -->
		<div ng-controller="programsController">
        <select name="program" id="program" ng-model="program"
        ng-options="prog.name for prog in programs">
        </select>
        RES {{program.name}}
        DOS {{selected_program}}
		</div>

<!-- comment -->
		<div ng-controller="periodsController">
        <select name="period" id="period" ng-model="period"
        ng-options="period.name for period in periods">
        </select>
		</div>

<!-- comment -->
		<div ng-controller="teacherController">
        <select name="teacher" id="teacher" ng-model="teacher"
        ng-options="teacher.name for teacher in teachers">
        </select>
		</div>

		<button ng-click="vals()">Click</button>

	</div>
El modulo principal es MyForm

angular.module('MyForm',['Programs','Periods','Teachers']) .factory('myFactory', function() { console.log('Factory loaded'); var course = { program : 'no set', setValues : function (program){ course.program=program; }, sayHello : function(){ alert('hello'); } } console.log(course); return course; }) .controller('mainController',['$scope','myFactory',function($scope,myFactory){ $scope.vals = function(){ //myFactory.setValues(myFactory.program); //myFactory.sayHello(); alert('The values are:' + '\nProgram: ' + myFactory.program + '\nProgram: ' + myFactory.period + '\nProgram: ' + myFactory.teacher); } }]) ;

 Los modulos Programs, Periods y Teachers son utilizados para los selects. Los hice en modulos porque esos mismos selects van a ser reutilizados en otras paginas y para evitar repeticion de codigo.

Otra forma que se me ocurre es repetir el codigo de cada controlador e incluirlo en un solo controlador para asi acceder al scope desde un solo controlador.


angular.module('Programs',[])
	    .factory('proFactory',function(){
	    	var selected_program = '0';
	    	console.log('From proFactory');
	    })

	    .controller('programsController',function($scope,myFactory){
	    	$scope.programs=[
	    	{ID:1 , name:'HTML'},
	    	{ID:2 , name: 'AngularJS'}
	    	];

	    	$scope.program = $scope.programs[0];
	    	//myFactory.setValues($scope.program.ID);
    });

	angular.module('Periods',[])
	    .controller('periodsController',function($scope){
		$scope.periods=[
	    	{ID:1 , name:'Jan-Feb'},
	    	{ID:2 , name: 'Mar-Apr'}
	    	];
	    $scope.period = $scope.periods[0];
	});

	angular.module('Teachers',[])
	    .controller('teacherController',function($scope){
	    $scope.teachers=[
	    	{ID:1 , name:'Mark Smith'},
	    	{ID:2 , name: 'Joe Cliff'}
	    	];
	    $scope.teacher = $scope.teachers[0];
	});

 El boton del html ejecuta la funcion vals() que esta en el scope del mainController, sin embargo he intentado varias maneras de asignar los valores de los selects a alguna variable.

<button ng-click="vals()">Click</button>

Leyendo encontre que para esto, es decir compartir o acceder a variables fuera del scope del controlador, hay que utilizar un provider, en este caso lo estoy intentado con un factory, y en el factory devolver un objeto que tenga los metodos (API) para asignar el valor a las variables, sin embargo aqui es donde estoy estancado.

	angular.module('Programs',[])
	    .factory('proFactory',function(){
	    	var selected_program = '0';
	    	console.log('From proFactory');
	    	    return {
			 set_program: (function(program){ selected_program = program; }),
		         get_program: (function(){ return selected_program; }),
		         sayHi : (function(){alert('hi from proFactory');})
			    };
	    })

¿Alguna idea para asignar los valores de los selects a alguna variable u objeto y mostrarlos en un alert o en la consola desde el mainController?

Gracias de antemano.

0
Hola Eduardo.

Tienes algunas opciones para solucionar este problema, te voy a comentar dos y tu decide cual te conviene más.

En primer lugar puedes indicarle en el modelo del input que la propiedad corresponderá al scope del controlador padre, eso lo haces mediante el objeto $parent de la siguiente manera.

<select name="program" id="program" ng-model="$parent.program"
        ng-options="prog.name for prog in programs">        
</select>

 Con eso la propiedad program se va a crear en el scope del main controller, permitiendo acceder a ella así.

.controller('mainController',['$scope','myFactory',function($scope,myFactory){
    var me = this;
    $scope.vals = function(){
        $scope.program.name //<----
    }
});

 La segunda opción es usar un alias para el controlador, de esta manera en el modelo del input especificas donde se creará la propiedad, por ejemplo.

<div id="container" ng-controller="mainController as main">

    <!-- comment -->
    <div ng-controller="periodsController">
        <select name="period" id="period" ng-model="main.period"
        ng-options="period.name for period in periods">
        </select>
    </div>
</div>

 Donde se declara el controler se crea un alias, en este caso main, luego en el ng-model usamos ese alias, de esa manera la propiedad period se va a crear dentro del controller, para accederla sería algo así:

.controller('mainController',['$scope','myFactory',function($scope,myFactory){
    var me = this;
    $scope.vals = function(){
        me.period.name //<-----
    }
});

Algo importante por mencionar es que la propiedad se crea directamente dentro de la instancia del controlador y no dentro del objeto scope.

Existe una técnica más llamada dot rule, si quieres luego te la explico, por el momento revisa los dos ejemplos que te puse y decide cual te conviene más, te dejo el link a JSBin para que veas el ejemplo funcionando.

http://jsbin.com/wehabuzuyo/1/edit?html,js,output

Saludos!
Eduardo Briseño: Muchas gracias Crysfel!!! lo hice por la primera, con el $parent.program. 09/01/2015

¿Conoces a alguien que pueda responder esta pregunta? Comparte el link en Twitter o Facebook

Es necesario registrarse para poder participar en el foro! Si ya tienes una cuenta puedes entrar y comentar en este foro.