Parece haver algumas maneiras de se comunicar entre diretivas. Digamos que você tenha diretivas aninhadas, nas quais as diretivas internas devem comunicar algo ao externo (por exemplo, foram escolhidas pelo usuário).
<outer>
<inner></inner>
<inner></inner>
</outer>
Até agora eu tenho 5 maneiras de fazer isso
require:
diretiva pai
A inner
diretiva pode exigir a outer
diretiva, que pode expor algum método em seu controlador. Então, na inner
definição
require: '^outer',
link: function(scope, iElement, iAttrs, outerController) {
// This can be passed to ng-click in the template
$scope.chosen = function() {
outerController.chosen(something);
}
}
E no outer
controlador da diretiva:
controller: function($scope) {
this.chosen = function(something) {
}
}
$emit
evento
A inner
diretiva pode $emit
um evento ao qual a outer
diretiva possa responder, via $on
. Portanto, no inner
controlador da diretiva:
controller: function($scope) {
$scope.chosen = function() {
$scope.$emit('inner::chosen', something);
}
}
e no outer
controlador de diretivas:
controller: function($scope) {
$scope.$on('inner::chosen, function(e, data) {
}
}
Executar expressão no escopo pai, via &
O item pode vincular-se a uma expressão no escopo pai e executá-la em um ponto apropriado. O HTML seria como:
<outer>
<inner inner-choose="functionOnOuter(item)"></inner>
<inner inner-choose="functionOnOuter(item)"></inner>
</outer>
Portanto, o inner
controlador possui uma função 'innerChoose' que pode ser chamada
scope: {
'innerChoose': '&'
},
controller: function() {
$scope.click = function() {
$scope.innerChoose({item:something});
}
}
que chamaria (neste caso) a função 'functionOnOuter' no outer
escopo da diretiva:
controller: function($scope) {
$scope.functionOnOuter = function(item) {
}
}
Herança de escopo em escopo não isolado
Dado que estes são controladores aninhados, a herança do escopo pode estar em funcionamento, e a diretiva interna pode simplesmente chamar quaisquer funções na cadeia de escopo, desde que não tenha um escopo isolado). Então, na inner
diretiva:
// scope: anything but a hash {}
controller: function() {
$scope.click = function() {
$scope.functionOnOuter(something);
}
}
E na outer
diretiva:
controller: function($scope) {
$scope.functionOnOuter = function(item) {
}
}
Por serviço injetado no interior e no exterior
Um serviço pode ser injetado nas duas diretivas, para que eles possam ter acesso direto ao mesmo objeto ou chamar funções para notificar o serviço e talvez até se registrar para serem notificados em um sistema de publicação / publicação. Isso não requer que as diretivas sejam aninhadas.
Pergunta : Quais são os possíveis inconvenientes e vantagens de cada um em relação aos outros?
fonte
Respostas:
Minha preferência é definir um
&
atributo no escopo da diretiva principalmente porque vejo ascope: {}
definição de uma diretiva como sua API. É muito mais fácil olhar para uma definição de atributo de escopo para ver quais informações a diretiva precisa para funcionar corretamente do que para vasculhar as funções de link e controlador em busca$emit
de eventos, funções de escopo herdadas ou funções usadas nos controladores injetados.fonte
Minha opinião:
Os serviços são a maneira preferida de compartilhar comportamentos / dados entre módulos / diretivas / controladores. Diretivas são coisas isoladas que podem ser aninhadas ou não. Os controladores devem permanecer o máximo possível de um modelo de exibição, idealmente, nenhuma lógica de negócios deve acabar aí.
Assim:
Quando você começa a conectá-los acessando as funções de escopo pai, acho que você corre o risco de acoplá-las com muita força e tornar todo o aplicativo ilegível e os componentes não reutilizáveis. Ao dissociar esses dados ou comportamentos compartilhados em um serviço, você tem o benefício de reutilizar as diretivas inteiras com dados / comportamentos diferentes, até mesmo determinando o serviço a ser usado no tempo de execução. Qual é o objetivo da injeção de dependência.
fonte