Mam dyrektywę, oto kod:
.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);
}
}
})
Chciałbym wezwać updateMap()
użytkownika do działania. Przycisk akcji nie znajduje się na dyrektywie.
Jak najlepiej dzwonić updateMap()
z kontrolera?
angularjs
angularjs-directive
Mcbjam
źródło
źródło
Odpowiedzi:
Jeśli chcesz użyć izolowanych zakresów, możesz przekazać obiekt sterujący za pomocą dwukierunkowego wiązania
=
zmiennej z zakresu kontrolera. Możesz także kontrolować kilka instancji tej samej dyrektywy na stronie z tym samym obiektem kontrolnym.źródło
scope.control
istnieje, w przeciwnym razie inne miejsca, które korzystają z dyrektywy, ale nie muszą uzyskiwać dostępu do metod dyrektywy i nie mającontrol
attr, zacznąundefined
Zakładając, że przycisk działania używa tego samego kontrolera
$scope
jako dyrektywy, wystarczy zdefiniować funkcjęupdateMap
na$scope
wewnątrz funkcji łącza. Kontroler może wtedy wywołać tę funkcję po kliknięciu przycisku akcji.fiddle
Zgodnie z komentarzem @ FlorianF, jeśli dyrektywa używa izolowanego zakresu, sprawy są bardziej skomplikowane. Oto jeden ze sposobów, aby działał: dodaj
set-fn
atrybut domap
dyrektywy, który zarejestruje funkcję dyrektywy w kontrolerze:fiddle
źródło
scope
właściwość do deklaracji dyrektywy.Chociaż może być kuszące, aby ujawnić obiekt na izolowanym zakresie dyrektywy, aby ułatwić komunikację z nim, działanie może prowadzić do mylącego kodu „spaghetti”, szczególnie jeśli trzeba połączyć tę komunikację na kilka poziomów (kontroler, dyrektywa, do dyrektywy zagnieżdżonej itp.)
Początkowo podążaliśmy tą ścieżką, ale po kilku dalszych badaniach okazało się, że ma to większy sens i zaowocowało zarówno łatwiejszym w utrzymaniu, jak i czytelnym kodem do ujawnienia zdarzeń i właściwości, których dyrektywa użyje do komunikacji za pośrednictwem usługi, a następnie za pomocą $ watch we właściwościach tej usługi w dyrektywa lub wszelkie inne mechanizmy kontrolne, które musiałyby reagować na te zmiany w zakresie komunikacji.
Ta abstrakcja działa bardzo dobrze z ramką wstrzykiwania zależności AngularJS, ponieważ można wstrzyknąć usługę do dowolnych elementów, które muszą zareagować na te zdarzenia. Jeśli spojrzysz na plik Angular.js, zobaczysz, że tam zawarte dyrektywy również używają usług i $ watch w ten sposób, nie ujawniają zdarzeń poza izolowanym zakresem.
Na koniec, w przypadku, gdy trzeba komunikować się między dyrektywami, które są od siebie zależne, zaleciłbym współużytkowanie kontrolera między tymi dyrektywami jako środka komunikacji.
Wiki AngularJS dla najlepszych praktyk wspomina również o tym:
źródło
=
, która zawiera nazwę metody i argumenty. (2) ujawnij ciąg powiązania jednokierunkowego@
jako identyfikator tematu i pozwól odbiorcy wysłać zdarzenie dotyczące tego tematu. Teraz zobaczyłem wiki najlepszych praktyk. Myślę, że istnieje powód, aby tego nie robić w jakiś sposób. Ale nadal nie jestem bardzo jasne, jak to działa. W moim przypadku utworzyłem dyrektywę dotyczącą tabel, chcę ujawnićswitchTab(tabIndex)
metodę. Czy możesz podać więcej przykładów?switchTab(tabIndex)
metody, wiązałbyś się tylko zetabIndex
zmienną. Kontroler strony może mieć działania, które zmieniają tę zmienną. Wiążesz / przekazujesz tę zmienną do swojej zakładki Dyrektywa. Dyrektywa zakładki może następnie obserwować tę zmienną pod kątem zmian i samodzielnie wykonać switchTab. Ponieważ dyrektywa decyduje, kiedy / jak kontrolować swoje zakładki na podstawie zmiennej. To nie jest zadanie zewnętrznego źródła, w przeciwnym razie źródła zewnętrzne wymagają znajomości wewnętrznych zasad funkcjonowania dyrektywy, co jest złe.Opierając się na odpowiedzi Olivera - nie zawsze możesz potrzebować dostępu do wewnętrznych metod dyrektywy, a w takich przypadkach prawdopodobnie nie chcesz tworzyć pustego obiektu i dodawać
control
atrybutu do dyrektywy, aby zapobiec zgłoszeniu błędu (cannot set property 'takeTablet' of undefined
).Możesz także chcieć użyć tej metody w innych miejscach dyrektywy.
Dodałbym sprawdzenie, aby upewnić się, że
scope.control
istnieje, i ustawiłem dla niego metody w podobny sposób, jak wzór modułu ujawniającegoźródło
Szczerze mówiąc, tak naprawdę nie byłem przekonany do żadnej odpowiedzi w tym wątku. Oto moje rozwiązania:
Podejście do obsługi dyrektywy (menedżera)
Ta metoda jest niezależna od tego, czy dyrektywa
$scope
jest wspólna, czy odizolowanaA,
factory
aby zarejestrować instancje dyrektywyKod dyrektywy, zwykle umieszczam całą logikę, która nie dotyczy DOM, w kontrolerze dyrektywy. I zarejestrowanie instancji kontrolera w naszym module obsługi
kod szablonu
Uzyskaj dostęp do instancji kontrolera za pomocą
factory
& uruchom publicznie udostępnione metodyPodejście Angulara
Wyciągając liść z książki Angulara o tym, jak sobie radzą
przy użyciu $ parsowania i rejestracji kontrolera na
$parent
zakresie. Ta technika nie działa na pojedyncze$scope
dyrektywy.Uzyskaj dostęp do kontrolera za pomocą
$scope.foo
źródło
$scope.foo
powinno być$scope.my_form
$scope.foo
ponieważ nasz szablon jest<div my-directive name="foo"></div>
iname
wartość atrybutu jest „foo”.<form
jest tylko przykładem jednej z dyrektyw kątowych, która stosuje tę technikęTrochę późno, ale jest to rozwiązanie z izolowanym zakresem i „zdarzeniami” do wywołania funkcji w dyrektywie. To rozwiązanie jest inspirowane tym postem SO autorstwa satchmorun i dodaje moduł oraz interfejs API.
Utwórz interfejs API do komunikacji z dyrektywą. AddUpdateEvent dodaje zdarzenie do tablicy zdarzeń, a updateMap wywołuje każdą funkcję zdarzenia.
(Być może musisz dodać funkcjonalność, aby usunąć zdarzenie).
W dyrektywie ustaw odwołanie do MapAPI i dodaj $ scope.updateMap jako zdarzenie po wywołaniu MapApi.updateMap.
W „głównym” kontrolerze dodaj odwołanie do MapApi i po prostu wywołaj MapApi.updateMap (), aby zaktualizować mapę.
źródło
Możesz określić atrybut DOM, którego można użyć, aby umożliwić dyrektywie zdefiniowanie funkcji w zakresie nadrzędnym. Zakres nadrzędny może następnie wywołać tę metodę jak każdą inną. Oto plunker. A poniżej znajduje się odpowiedni kod.
clearfn
jest atrybutem elementu dyrektywy, do którego zakres nadrzędny może przekazać właściwość zakresu, którą dyrektywa może następnie ustawić na funkcję spełniającą pożądane zachowanie.źródło
scope: { clearFn: '=clearfn' }
.).Wystarczy użyć scope. $ Parent, aby powiązać funkcję wywoływaną z funkcją dyrektywy
w HTML
źródło
Możesz podać nazwę metody do dyrektywy, aby zdefiniować, który chcesz wywołać ze sterownika, ale bez izolowania zakresu,
źródło
TESTOWANE Mam nadzieję, że to komuś pomoże.
Moje proste podejście (myśl tagi jako swój oryginalny kod)
źródło
Być może nie jest to najlepszy wybór, ale możesz zrobić
angular.element("#element").isolateScope()
lub$("#element").isolateScope()
uzyskać dostęp do zakresu i / lub kontrolera swojej dyrektywy.źródło
Jak uzyskać kontroler dyrektywy w kontrolerze strony:
napisz niestandardową dyrektywę, aby uzyskać odwołanie do kontrolera dyrektywy z elementu DOM:
użyj go w html kontrolera strony:
Użyj kontrolera dyrektywy w kontrolerze strony:
Uwaga: dane rozwiązanie działa tylko dla kontrolerów dyrektyw elementowych (nazwa znacznika służy do uzyskania nazwy żądanej dyrektywy).
źródło
Poniższe rozwiązanie przyda się, gdy masz kontrolery (nadrzędne i dyrektywy (izolowane)) w formacie „kontrolera jako”
ktoś może uznać to za przydatne,
dyrektywa:
kontroler dyrektywy:
Kod HTML :
źródło