Eu tenho uma diretiva, aqui está o código:
.directive('map', function() {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
link: function($scope, element, attrs) {
var center = new google.maps.LatLng(50.1, 14.4);
$scope.map_options = {
zoom: 14,
center: center,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// create map
var map = new google.maps.Map(document.getElementById(attrs.id), $scope.map_options);
var dirService= new google.maps.DirectionsService();
var dirRenderer= new google.maps.DirectionsRenderer()
var showDirections = function(dirResult, dirStatus) {
if (dirStatus != google.maps.DirectionsStatus.OK) {
alert('Directions failed: ' + dirStatus);
return;
}
// Show directions
dirRenderer.setMap(map);
//$scope.dirRenderer.setPanel(Demo.dirContainer);
dirRenderer.setDirections(dirResult);
};
// Watch
var updateMap = function(){
dirService.route($scope.dirRequest, showDirections);
};
$scope.$watch('dirRequest.origin', updateMap);
google.maps.event.addListener(map, 'zoom_changed', function() {
$scope.map_options.zoom = map.getZoom();
});
dirService.route($scope.dirRequest, showDirections);
}
}
})
Eu gostaria de ligar updateMap()
uma ação do usuário. O botão de ação não está na diretiva.
Qual é a melhor maneira de ligar updateMap()
de um controlador?
angularjs
angularjs-directive
mcbjam
fonte
fonte
Respostas:
Se você deseja usar escopos isolados, pode passar um objeto de controle usando a ligação bidirecional
=
de uma variável do escopo do controlador. Você também pode controlar várias instâncias da mesma diretiva em uma página com o mesmo objeto de controle.fonte
scope.control
exista, caso contrário, outros locais que usam a diretiva, mas não precisam acessar os métodos da diretiva e não possuem umcontrol
atributo, começarão a gerar erros por não conseguir definir atributosundefined
Supondo-se que o botão de ação usa o mesmo controlador
$scope
como a directiva, apenas definir a funçãoupdateMap
de$scope
dentro da função de ligação. Seu controlador pode chamar essa função quando o botão de ação é clicado.fiddle
Conforme o comentário do @ FlorianF, se a diretiva usa um escopo isolado, as coisas são mais complicadas. Aqui está uma maneira de fazê-lo funcionar: adicione um
set-fn
atributo àmap
diretiva que registrará a função de diretiva no controlador:fiddle
fonte
scope
propriedade na declaração da diretiva.Embora possa ser tentador expor um objeto no escopo isolado de uma diretiva para facilitar a comunicação com ela, isso pode levar a códigos "spaghetti" confusos, especialmente se você precisar encadear essa comunicação por alguns níveis (controlador, diretiva, diretiva aninhada etc.)
Originalmente, seguimos esse caminho, mas depois de mais algumas pesquisas, descobrimos que fazia mais sentido e resultava em um código mais sustentável e legível para expor eventos e propriedades que uma diretiva usará para comunicação por meio de um serviço, em seguida, usando $ watch nas propriedades desse serviço em a diretiva ou quaisquer outros controles que precisem reagir a essas alterações na comunicação.
Essa abstração funciona muito bem com a estrutura de injeção de dependência do AngularJS, pois você pode injetar o serviço em qualquer item que precise reagir a esses eventos. Se você observar o arquivo Angular.js, verá que as diretivas também usam serviços e $ watch dessa maneira, mas não expõem eventos no escopo isolado.
Por fim, no caso de você precisar se comunicar entre diretivas que dependem uma da outra, eu recomendaria compartilhar um controlador entre essas diretivas como meio de comunicação.
O Wiki de Boas Práticas do AngularJS também menciona isso:
fonte
=
, a variável contém o nome e os argumentos do método. (2) exponha uma string de ligação unidirecional@
como identificação do tópico e permita que o receptor envie evento sobre esse tópico. Agora eu vi o wiki de melhores práticas. Eu acho que há razões para não fazê-lo de maneira diferente. Mas ainda não estou muito claro como isso funciona. No meu caso, eu criei uma diretiva tabset, quero expor umswitchTab(tabIndex)
método. Você poderia exemplificar mais?switchTab(tabIndex)
método, apenas vinculou a umatabIndex
variável. Seu controlador de página pode ter ações que alteram essa variável. Você vincula / passa essa variável para a guia Diretiva. A guia Diretiva pode assistir a essa variável em busca de alterações e executar o switchTab por conta própria. Porque a diretiva decide quando / como controlar suas guias com base em uma variável. Esse não é o trabalho de uma fonte externa; caso contrário, as fontes externas exigem conhecimento do funcionamento interno da diretiva, o que é ruim.Com base na resposta de Oliver - nem sempre é necessário acessar os métodos internos de uma diretiva e, nesses casos, você provavelmente não deseja criar um objeto em branco e adicionar um
control
attr à diretiva apenas para impedir que ela gere um erro (cannot set property 'takeTablet' of undefined
)Você também pode querer usar o método em outros locais da diretiva.
Eu adicionaria uma verificação para garantir que
scope.control
exista e definiria métodos de maneira semelhante ao padrão do módulo reveladorfonte
Para ser sincero, não estava realmente convencido de nenhuma das respostas neste tópico. Então, aqui estão minhas soluções:
Abordagem do manipulador de diretivas (gerente)
Este método é independente do fato de a diretiva
$scope
ser compartilhada ou isoladaA
factory
para registrar as instâncias da diretivaO código de diretiva, eu costumo colocar toda a lógica que não lida com o DOM dentro do controlador de diretiva. E registrando a instância do controlador dentro de nosso manipulador
código do modelo
Acesse a instância do controlador usando os
factory
métodos & execute publicamente expostosAbordagem da Angular
Tirando uma folha do livro da angular sobre como eles lidam com
usando $ parse e registrando o controlador no
$parent
escopo. Essa técnica não funciona em$scope
diretivas isoladas .Acesse-o dentro do controlador usando
$scope.foo
fonte
$scope.foo
deve ser$scope.my_form
$scope.foo
porque nosso modelo é<div my-directive name="foo"></div>
ename
o valor do atributo é 'foo'.<form
é apenas um exemplo de um de directiva da angular que emprega essa técnicaUm pouco tarde, mas esta é uma solução com o escopo isolado e "eventos" para chamar uma função na diretiva. Esta solução é inspirada nesta postagem de SO da satchmorun e adiciona um módulo e uma API.
Crie uma API para se comunicar com a diretiva. O addUpdateEvent adiciona um evento à matriz de eventos e o updateMap chama todas as funções de eventos.
(Talvez você precise adicionar funcionalidade para remover o evento.)
Na diretiva, defina uma referência ao MapAPI e inclua $ scope.updateMap como um evento quando MapApi.updateMap for chamado.
No controlador "main", adicione uma referência ao MapApi e chame MapApi.updateMap () para atualizar o mapa.
fonte
Você pode especificar um atributo DOM que pode ser usado para permitir que a diretiva defina uma função no escopo pai. O escopo pai pode chamar esse método como qualquer outro. Aqui está um afundador. E abaixo está o código relevante.
clearfn
é um atributo no elemento de diretiva no qual o escopo pai pode transmitir uma propriedade de escopo que a diretiva pode definir para uma função que realiza o comportamento desejado.fonte
scope: { clearFn: '=clearfn' }
).Basta usar o scope. $ Parent para associar a função chamada à função de diretiva
em HTML
fonte
Você pode dizer ao nome do método a diretiva para definir qual você deseja chamar do controlador, mas sem isolar o escopo,
fonte
TESTADO Espero que isso ajude alguém.
Minha abordagem simples (pense em tags como seu código original)
fonte
Talvez essa não seja a melhor opção, mas você pode fazer
angular.element("#element").isolateScope()
ou$("#element").isolateScope()
acessar o escopo e / ou o controlador de sua diretiva.fonte
Como obter o controlador de uma diretiva em um controlador de página:
escreva uma diretiva personalizada para obter a referência ao controlador de diretiva a partir do elemento DOM:
use-o no html do controlador de página:
Use o controlador de diretiva no controlador de página:
Nota: a solução fornecida funciona apenas para controladores de diretivas de elemento (o nome da tag é usado para obter o nome da diretiva desejada).
fonte
A solução abaixo será útil quando você tiver controladores (pai e diretiva (isolados)) no formato 'controller As'
alguém pode achar isso útil,
directiva:
diretiva Controller:
Código HTML :
fonte