ejemplo directivas angularjs angularjs-directive angularjs-scope angular-controller angularjs-controlleras

angularjs - ejemplo - Problemas con las directivas anidadas angulares al usar ControllerAs



ng-bind (1)

Básicamente, debe usar la opción require of directive (la opción require se utiliza para directivas de comunicación con directivas). Lo cual dará acceso a su controlador principal simplemente mencionando la opción require en la directiva hija. También necesita usar bindToController: true que básicamente agregará datos de ámbito aislado al controlador de directivas.

Código

function formBuilder() { return { restrict: ''A'', replace: true, bindToController: true, scope: { formData: ''='' }, templateUrl: ''FormBuilder.html'', controller: function($scope) { $scope.formSubmit = function() { // Submits the formData.formFields and formData.photoFields // to the server // The data for these objects are created through // the child directives below } } } }

Luego debe agregar la opción require a las directivas secundarias. Básicamente, la opción require tendrá la directiva formBuilder con ^ (indica que formBuilder estará allí en el elemento padre) como require: ''^formBuilder'',

Al escribir una opción de require , puede obtener el controlador de esa directiva en el cuarto parámetro de la función de enlace.

Código

function formFields() { return { restrict: ''A'', replace: true, require: ''^formBuilder'', templateUrl: ''FormFields.html'', //4th parameter is formBuilder controller link: function(scope, element, attrs, formBuilderCtrl){ scope.formBuilderCtrl = formBuilderCtrl; }, controller: function($scope, $timeout) { var vm = this; //getting the `formData` from `formBuilderCtrl` object //added timeout here to run code after link function, means after next digest $timeout(function(){ console.log($scope.formBuilderCtrl.formData.formFields); }) } } } function photoFields() { return { restrict: ''A'', replace: true, require: ''^formBuilder'', templateUrl: ''PhotoFields.html'', //4th parameter is formBuilder controller link: function(scope, element, attrs, formBuilderCtrl){ scope.formBuilderCtrl = formBuilderCtrl; }, controller: function($scope, $timeout) { var vm = this; console.log(vm.formData.photoFields); //to run the code in next digest cycle, after link function gets called. $timeout(function(){ console.log($scope.formBuilderCtrl.formData.formFields); }) } } }

Editar

Un problema con la solución anterior es que, para tener acceso al controlador de la directiva principal en el controlador de directivas, he hecho algunas cosas complicadas. Primero, incluya el formBuilderCtrl a la variable de ámbito del cuarto parámetro de la función de enlace. Entonces solo usted puede obtener acceso a ese controlador usando $scope (que no desea allí). Con respecto al mismo problema registrado en Github con estado abierto , puedes verificarlo aquí.

Estoy construyendo una gran forma que llama varias directivas para construir una forma completa. La página principal que llama al generador de formularios pasa los datos del modelo ng así:

<div form-builder form-data=“formData”></div>

Luego, la página de creación de formularios llama a varias directivas para niños para compilar varias secciones del formulario:

FormBuilder.html: <div form-fields></div> <div photo-fields></div> <div video-fields></div> .. etc.. etc...

Al usar $scope en el controlador, no tuve ningún problema para acceder al $scope en las directivas secundarias como esta:

function formBuilder() { return { restrict: ''A'', replace: true, scope: { formData: ''='' }, templateUrl: ''FormBuilder.html'', controller: function($scope) { $scope.formSubmit = function() { // Submits the formData.formFields and formData.photoFields // to the server // The data for these objects are created through // the child directives below } } } } function formFields() { return { restrict: ''A'', replace: true, templateUrl: ''FormFields.html'', controller: function($scope) { console.log($scope.formData.formFields); } } } function photoFields() { return { restrict: ''A'', replace: true, templateUrl: ''PhotoFields.html'', controller: function($scope) { console.log($scope.formData.photoFields); } } } ... etc..

Pero desde que me deshice del $scope y comencé a usar ControllerAs , tengo todo tipo de problemas para acceder al enlace bidireccional con Parent-Child Controllers.

function formBuilder() { return { restrict: ''A'', replace: true, scope: { formData: ''='' }, templateUrl: ''FormBuilder.html'', controller: function() { var vm = this; console.log(vm.formData); // Its fine here vm.formSubmit = function() { // I cannot change formData.formFields and formData.photoFields // from Child Directive "Controllers" } }, controllerAs: ‘fb’, bindToController: true } } function formFields() { return { restrict: ''A'', replace: true, templateUrl: ''FormFields.html'', controller: function() { var vm = this; console.log(vm.formData.formFields); // No way to access 2 way binding with this Object!!! } } } function photoFields() { return { restrict: ''A'', replace: true, templateUrl: ''PhotoFields.html'', controller: function() { var vm = this; console.log(vm.formData.photoFields); // No way to access 2 way binding with this Object!!! } } }

Cualquier cosa que intento, estoy llegando a un bloque de carreteras. Las cosas que he intentado son:

  1. Ámbitos aislados: Intenté pasar formData.formFields y formData.photoFields como ámbitos aislados a la directiva hija, pero luego termino obteniendo el error $compile: MultiDir debido a ámbitos aislados anidados, por lo que no es posible.
  2. Si no tengo directivas individuales para cada sección del formulario y las tengo todas en 1 directiva bajo la directiva formBuilder , entonces se convierte en una directiva humillante. Lo anterior es solo un boceto, pero cada directiva para niños construye 1 gran formulario al final. Así que fusionarlos es realmente el último recurso, ya que se vuelve difícil de mantener e ilegible.
  3. No creo que haya una forma de acceder a ControllerAs la Directiva Parent de ControllerAs de la Directiva Child de otra manera que lo que he visto hasta ahora.
  4. Si utilizo las ControllerAs de la matriz en el ng-model de la plantilla de la directiva child como <input type=“text” ng-model=“fb.formData.formFields.text" /> , eso funciona bien, pero necesito acceder a la misma desde el controlador de la directiva Child para algún procesamiento que no puedo hacer.
  5. Si me deshago de los controllerAs y uso el $scope nuevamente, funciona igual que antes, pero estoy tratando de deshacerme del $scope para prepararme para futuros cambios angulares.

Como es un formulario avanzado, necesito tener una directiva separada para manejar varias secciones de formularios y, dado que los ámbitos anidados no están permitidos desde Angular 1.2, lo hace cada vez más difícil, especialmente cuando se trata de deshacerse de $scope usando ControllerAs .

¿Puede alguien guiarme cuáles son mis opciones aquí, por favor? Te agradezco por leer mi larga publicación.