Ich habe eine Anweisung, hier ist der Code:
.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);
}
}
})
Ich möchte updateMap()
eine Benutzeraktion aufrufen . Die Aktionsschaltfläche befindet sich nicht in der Direktive.
Was ist der beste Weg, um updateMap()
von einem Controller aus anzurufen ?
angularjs
angularjs-directive
mcbjam
quelle
quelle
Antworten:
Wenn Sie isolierte Bereiche verwenden möchten, können Sie ein Steuerobjekt übergeben, indem Sie
=
eine Variable aus dem Controller-Bereich bidirektional binden . Sie können auch mehrere Instanzen derselben Direktive auf einer Seite mit demselben Steuerobjekt steuern.quelle
scope.control
, dass andere Stellen, die die Direktive verwenden, aber nicht auf die Methoden der Direktive zugreifen müssen und keinecontrol
attr haben, Fehler auslösen, wenn sie keine Attributeundefined
Unter der Annahme , daß die Aktionstaste verwendet den gleichen Controller
$scope
als Richtlinie definiert gerade FunktionupdateMap
auf$scope
innerhalb der Link - Funktion. Ihr Controller kann diese Funktion dann aufrufen, wenn Sie auf die Aktionsschaltfläche klicken.fiddle
Laut dem Kommentar von @ FlorianF sind die Dinge komplizierter, wenn die Richtlinie einen isolierten Geltungsbereich verwendet. Hier ist eine Möglichkeit, wie es funktioniert: Fügen Sie
set-fn
dermap
Direktive ein Attribut hinzu, das die Direktivenfunktion beim Controller registriert:fiddle
quelle
scope
Eigenschaft zur Direktivendeklaration hinzufügen .Obwohl es möglicherweise verlockend ist, ein Objekt dem isolierten Geltungsbereich einer Direktive auszusetzen, um die Kommunikation mit ihr zu erleichtern, kann dies zu verwirrendem "Spaghetti" -Code führen, insbesondere wenn Sie diese Kommunikation über mehrere Ebenen verketten müssen (Controller, Direktive, zu verschachtelten Direktiven usw.)
Wir sind diesen Weg ursprünglich gegangen, aber nach einigen weiteren Untersuchungen stellte sich heraus, dass dies sinnvoller war und sowohl zu wartbarem als auch zu lesbarem Code führte, um Ereignisse und Eigenschaften verfügbar zu machen, die eine Direktive für die Kommunikation über einen Dienst verwendet, und dann $ watch für die Eigenschaften dieses Dienstes in zu verwenden die Richtlinie oder andere Kontrollen, die auf diese Änderungen für die Kommunikation reagieren müssten.
Diese Abstraktion funktioniert sehr gut mit AngularJSs Framework für die Abhängigkeitsinjektion, da Sie den Service in alle Elemente einfügen können, die auf diese Ereignisse reagieren müssen. Wenn Sie sich die Datei Angular.js ansehen, werden Sie feststellen, dass die dortigen Anweisungen auch Dienste und $ watch auf diese Weise verwenden. Sie machen keine Ereignisse über den isolierten Bereich verfügbar.
Für den Fall, dass Sie zwischen voneinander abhängigen Direktiven kommunizieren müssen, würde ich empfehlen, einen Controller zwischen diesen Direktiven als Kommunikationsmittel zu verwenden.
AngularJSs Wiki for Best Practices erwähnt dies auch:
quelle
=
. Die Variable enthält den Methodennamen und die Argumente. (2) Stellen Sie eine Einweg-Bindungszeichenfolge@
als Themen-ID bereit und lassen Sie den Angerufenen ein Ereignis zu diesem Thema senden. Jetzt habe ich das Best Practice Wiki gesehen. Ich denke, es gibt Grund, es nicht im Mai zu tun. Aber ich bin mir immer noch nicht ganz sicher, wie es funktioniert. In meinem Fall habe ich eine Tabset-Direktive erstellt, ich möchte eineswitchTab(tabIndex)
Methode verfügbar machen . Könnten Sie mehr Beispiel?switchTab(tabIndex)
Methode verfügbar machen, sondern nur an einetabIndex
Variable binden . Ihr Seitencontroller verfügt möglicherweise über Aktionen, die diese Variable ändern. Sie binden / übergeben diese Variable an Ihre Registerkarte Direktive. Ihre Tab-Direktive kann diese Variable dann auf Änderungen überwachen und switchTab von selbst ausführen. Weil die Direktive anhand einer Variablen entscheidet, wann / wie ihre Registerkarten gesteuert werden sollen. Das ist nicht die Aufgabe einer externen Quelle, sonst erfordern die externen Quellen Kenntnisse über das Innenleben der Richtlinie, was schlecht ist.Aufbauend auf Olivers Antwort - Sie müssen möglicherweise nicht immer auf die inneren Methoden einer Direktive zugreifen, und in diesen Fällen möchten Sie wahrscheinlich kein leeres Objekt erstellen und
control
der Direktive ein attr hinzufügen müssen, um zu verhindern, dass sie einen Fehler auslöst (cannot set property 'takeTablet' of undefined
).Möglicherweise möchten Sie die Methode auch an anderen Stellen innerhalb der Direktive verwenden.
Ich würde eine Prüfung hinzufügen, um sicherzustellen, dass sie
scope.control
vorhanden ist, und Methoden dafür festlegen, die dem aufschlussreichen Modulmuster ähnelnquelle
Um ehrlich zu sein, war ich von keiner der Antworten in diesem Thread wirklich überzeugt. Hier sind meine Lösungen:
Ansatz des Direktivenhandlers (Managers)
Diese Methode ist unabhängig davon, ob die Richtlinie
$scope
um eine gemeinsame oder eine isolierte handeltA
factory
, um die Instanzen der Direktive zu registrierenBeim Direktivencode habe ich normalerweise die gesamte Logik, die sich nicht mit DOM befasst, in den Direktiven-Controller eingefügt. Und Registrieren der Controller-Instanz in unserem Handler
Vorlagencode
Greifen Sie mit
factory
den öffentlich verfügbaren Methoden auf die Controller-Instanz zuAngulars Ansatz
Nehmen Sie ein Blatt aus Angulars Buch darüber, wie sie damit umgehen
Verwenden von $ parse und Registrieren des Controllers für den
$parent
Bereich. Diese Technik funktioniert nicht bei isolierten$scope
Anweisungen.Greifen Sie mit dem Controller darauf zu
$scope.foo
quelle
$scope.foo
sollte sein$scope.my_form
$scope.foo
da unsere Vorlage ist<div my-directive name="foo"></div>
undname
der Wert des Attributs 'foo' ist.<form
ist nur ein Beispiel für eine der Winkelanweisungen, die diese Technik anwendenEin bisschen spät, aber dies ist eine Lösung mit dem isolierten Bereich und "Ereignissen", um eine Funktion in der Direktive aufzurufen. Diese Lösung ist von diesem SO-Beitrag von satchmorun inspiriert und fügt ein Modul und eine API hinzu.
Erstellen Sie eine API für die Kommunikation mit der Direktive. Das addUpdateEvent fügt dem Ereignisarray ein Ereignis hinzu und updateMap ruft jede Ereignisfunktion auf.
(Möglicherweise müssen Sie Funktionen hinzufügen, um das Ereignis zu entfernen.)
Legen Sie in der Direktive einen Verweis auf die MapAPI fest und fügen Sie $ scope.updateMap als Ereignis hinzu, wenn MapApi.updateMap aufgerufen wird.
Fügen Sie im "Haupt" -Controller einen Verweis auf MapApi hinzu und rufen Sie einfach MapApi.updateMap () auf, um die Map zu aktualisieren.
quelle
Sie können ein DOM-Attribut angeben, mit dem die Direktive eine Funktion für den übergeordneten Bereich definieren kann. Der übergeordnete Bereich kann diese Methode dann wie jede andere aufrufen. Hier ist ein Plunker. Und unten ist der relevante Code.
clearfn
ist ein Attribut für das Direktivenelement, an das der übergeordnete Bereich eine Bereichseigenschaft übergeben kann, die die Direktive dann auf eine Funktion setzen kann, die das gewünschte Verhalten erreicht.quelle
scope: { clearFn: '=clearfn' }
. B. ).Verwenden Sie einfach scope. $ Parent, um die Funktion der Direktivenfunktion zuzuordnen
in HTML
quelle
Sie können den Methodennamen der Direktive mitteilen, um zu definieren, welche vom Controller aufgerufen werden soll, ohne jedoch den Bereich zu isolieren.
quelle
GEPRÜFT Hoffe das hilft jemandem.
Mein einfacher Ansatz (Think Tags als Originalcode)
quelle
Vielleicht ist dies nicht die beste Wahl, aber Sie können den Geltungsbereich und / oder den Controller Ihrer Direktive verwenden
angular.element("#element").isolateScope()
oder$("#element").isolateScope()
darauf zugreifen.quelle
So erhalten Sie den Controller einer Direktive in einen Seitencontroller:
Schreiben Sie eine benutzerdefinierte Direktive, um den Verweis auf den Direktiven-Controller vom DOM-Element abzurufen:
Verwenden Sie es im HTML-Code des Seitencontrollers:
Verwenden Sie den Direktiven-Controller im Seiten-Controller:
Hinweis: Die angegebene Lösung funktioniert nur für Controller von Elementanweisungen (der Tag-Name wird verwendet, um den Namen der gewünschten Anweisung abzurufen).
quelle
Die folgende Lösung ist hilfreich, wenn Sie Controller (sowohl übergeordnete als auch Direktive (isoliert)) im Format "Controller As" haben
jemand könnte dies nützlich finden,
Richtlinie:
Direktive Controller:
HTML Quelltext :
quelle