Comunicación entre directivas anidadas

58

Parece que hay varias formas de comunicación entre las directivas. Supongamos que tiene directivas anidadas, donde las directivas internas deben comunicar algo a las externas (por ejemplo, el usuario lo ha elegido).

<outer>
  <inner></inner>
  <inner></inner>
</outer>

Hasta ahora tengo 5 formas de hacer esto

require: directiva principal

La directiva inner puede requerir la directiva outer , que puede exponer algún método en su controlador. Así que en la definición inner

require: '^outer',
link: function(scope, iElement, iAttrs, outerController) {
   // This can be passed to ng-click in the template
   $scope.chosen = function() {
     outerController.chosen(something);
   }
}

Y en el controlador de la directiva outer :

controller: function($scope) {
   this.chosen = function(something) {
   }
}

$emit evento

La directiva inner puede $emit un evento, al que la directiva outer puede responder, a través de $on . Así que en el controlador de la directiva inner :

controller: function($scope) {
  $scope.chosen = function() {
    $scope.$emit('inner::chosen', something);
  }
}

y en el controlador de directivas outer :

controller: function($scope) {
  $scope.$on('inner::chosen, function(e, data) {
  }
}

Ejecutar expresión en el ámbito principal, a través de &

El elemento puede vincularse a una expresión en el ámbito principal y ejecutarlo en un punto apropiado. El HTML sería como:

<outer>
  <inner inner-choose="functionOnOuter(item)"></inner>
  <inner inner-choose="functionOnOuter(item)"></inner>
</outer>

Entonces el controlador inner tiene una función 'innerChoose' que puede llamar

scope: {
  'innerChoose': '&'
},
controller: function() {
  $scope.click = function() {
    $scope.innerChoose({item:something});
  }
}

que llamaría (en este caso) la función 'functionOnOuter' en el alcance de la directiva outer :

controller: function($scope) {
  $scope.functionOnOuter = function(item) {
  }
}

Herencia de alcance en alcance no aislado

Dado que estos son controladores anidados, la herencia del alcance puede estar en funcionamiento, y la directiva interna puede simplemente llamar a cualquier función en la cadena de alcance, siempre que no tenga un alcance aislado). Así que en la directiva inner :

// scope: anything but a hash {}
controller: function() {
  $scope.click = function() {
    $scope.functionOnOuter(something);
  }
}

Y en la directiva outer :

controller: function($scope) {
  $scope.functionOnOuter = function(item) {
  }
}

Por servicio inyectado en interior y exterior

Se puede inyectar un servicio en ambas directivas, de modo que puedan tener acceso directo al mismo objeto, o llamar a funciones para notificar al servicio, y tal vez incluso registrarse para ser notificados, en un pub / subsistema. Esto no requiere que las directivas estén anidadas.

Pregunta : ¿Cuáles son los posibles inconvenientes y ventajas de cada uno sobre los demás?

    
pregunta Michal Charemza 03.01.2014 - 11:21

2 respuestas

7

Mi preferencia es para definir un atributo & en el ámbito de la directiva principalmente porque veo la definición scope: {} de una directiva como su API. Es mucho más fácil ver una definición de atributo de alcance para ver qué información necesita la directiva para funcionar correctamente que para rastrear las funciones de enlace y controlador para los eventos $emit 'd, funciones de alcance heredadas o funciones utilizadas en los controladores inyectados.

    
respondido por el Jeff Swensen 09.03.2014 - 13:58
1

Mi opinión:

Los servicios son la forma preferida de compartir comportamientos / datos entre módulos / directivas / controladores. Las directivas son cosas aisladas que pueden ser anidadas o no. Los controladores deben seguir siendo un modelo de visualización tanto como puedan, idealmente, ninguna lógica de negocios debería terminar ahí.

Entonces:

Cuando empiece a cablearlos juntos accediendo a las funciones de alcance principal, creo que corre el riesgo de acoplarlas demasiado y hacer que la aplicación completa sea ilegible y los componentes no reutilizables. Cuando desacopla los datos o comportamientos compartidos en un servicio, tiene la ventaja de reutilizar todas las directivas con diferentes datos / comportamientos, incluso determinando el servicio que se utilizará en el tiempo de ejecución. De eso se trata la inyección de dependencia.

    
respondido por el RobbyD 27.01.2016 - 11:06

Lea otras preguntas en las etiquetas