it-swarm.com.de

Erweiterung Angular Direktive

Ich möchte eine geringfügige Änderung an einer Direktive eines Drittanbieters vornehmen (insbesondere Angular UI Bootstrap ). Ich möchte nur den Geltungsbereich der pane -Direktive erweitern:

angular.module('ui.bootstrap.tabs', [])
.controller('TabsController', ['$scope', '$element', function($scope, $element) {
  // various methods
}])
.directive('tabs', function() {
  return {
    // etc...
  };
})
.directive('pane', ['$parse', function($parse) {
  return {
    require: '^tabs',
    restrict: 'EA',
    transclude: true,
    scope:{
      heading:'@',
      disabled:'@' // <- ADDED SCOPE PROPERTY HERE
    },
    link: function(scope, element, attrs, tabsCtrl) {
      // link function
    },
    templateUrl: 'template/tabs/pane.html',
    replace: true
  };
}]);

Ich möchte Angular-Bootstrap aber auch mit Bower auf dem Laufenden halten. Sobald ich bower update, Ich werde meine Änderungen überschreiben.

Wie erweitere ich diese Richtlinie getrennt von dieser Laubkomponente?

114
Kyle

Der wahrscheinlich einfachste Weg, dies zu lösen, besteht darin, in Ihrer App eine Direktive mit demselben Namen wie die Direktive eines Drittanbieters zu erstellen. Beide Direktiven werden ausgeführt und Sie können ihre Ausführungsreihenfolge mit der Eigenschaft priority angeben (höhere Priorität wird zuerst ausgeführt).

Die beiden Direktiven teilen sich den Gültigkeitsbereich und Sie können über die link -Methode Ihrer Direktive auf den Gültigkeitsbereich der Direktive von Drittanbietern zugreifen und diesen ändern.

Option 2: Sie können auch auf den Geltungsbereich einer Drittanbieter-Direktive zugreifen, indem Sie einfach Ihre eigene, willkürlich benannte Direktive auf dasselbe Element setzen (vorausgesetzt, keine der Direktiven verwendet Isolate Umfang). Alle nicht isolierten Gültigkeitsbereichsanweisungen für ein Element haben denselben Gültigkeitsbereich.

Weiterführende Literatur: https://github.com/angular/angular.js/wiki/Dev-Guide%3A-Understanding-Directives

Hinweis: Meine vorherige Antwort betraf die Änderung eines Drittanbieter-Dienstes, nicht einer Direktive.

96
Dan

TL; DR - gib mir die Demo!


Big Demo Button


Verwenden Sie $provide 'S decorator() , um die Direktive des Dritten zu dekorieren.

In unserem Fall können wir den Geltungsbereich der Richtlinie folgendermaßen erweitern:

app.config(function($provide) {
    $provide.decorator('paneDirective', function($delegate) {
        var directive = $delegate[0];
        angular.extend(directive.scope, {
            disabled:'@'
        });
        return $delegate;
    });
});

Zuerst fordern wir an, die Direktive pane zu dekorieren, indem wir als erstes Argument den mit Directive verketteten Namen übergeben. Anschließend rufen wir ihn über den Callback-Parameter ab (ein Array von Direktiven, die mit diesem Namen übereinstimmen) ).

Sobald wir es erhalten haben, können wir es abrufen und nach Bedarf erweitern. Beachten Sie, dass dies alles im Block config erfolgen muss.

Einige Notizen

  • Es wurde vorgeschlagen, einfach eine Direktive mit demselben Namen hinzuzufügen und dann ihre Prioritätsstufe festzulegen. Abgesehen davon, dass es unsemantisch ist (was nicht einmal ein Wort ist, weiß ich…), wirft es Probleme auf, z. Was ist, wenn sich die Prioritätsstufe der Richtlinie eines Drittanbieters ändert?

  • JeetendraChauhan hat behauptet (ich habe es jedoch nicht getestet), dass diese Lösung in Version 1.13 nicht funktionieren wird.

60
Eliran Malka

Obwohl dies nicht die direkte Antwort auf Ihre Frage ist, möchten Sie vielleicht wissen, dass die neueste Version (in master) von http://angular-ui.github.io/bootstrap/ Unterstützung für das Deaktivieren von Tabs hinzugefügt hat . Diese Funktion wurde hinzugefügt durch: https://github.com/angular-ui/bootstrap/commit/2b78dd16abd7e09846fa484331b5c35ece6619a2

Eine andere Lösung, bei der Sie eine neue Direktive erstellen, die diese erweitert, ohne die ursprüngliche Direktive zu ändern

Die Lösung ähnelt der Dekorationslösung:

Erstellen Sie eine neue Direktive und fügen Sie als Abhängigkeit die Direktive ein, die Sie erweitern möchten

app.directive('extendedPane', function (paneDirective) {

  // to inject a directive as a service append "Directive" to the directive name
  // you will receive an array of directive configurations that match this 
  // directive (usually only one) ordered by priority

  var configExtension = {
     scope: {
       disabled: '@'
     }
  }

  return angular.merge({}, paneDirective[0], configExtension)
});

Auf diese Weise können Sie die ursprüngliche Direktive und die erweiterte Version in derselben App verwenden

6
kidroca

Hier ist eine andere Lösung für ein anderes Szenario zum Erweitern von Bindungen auf eine Direktive mit der Eigenschaft bindToController.

Hinweis: Dies ist keine Alternative zu anderen hier angebotenen Lösungen. Es wird nur ein spezifischer Fall gelöst (der in anderen Antworten nicht behandelt wird), in dem die ursprüngliche Direktive mit bindToController eingerichtet wurde.

1
gilad mayani