webentwicklung-frage-antwort-db.com.de

Wie kann ich in AngularJS dynamisch eine Direktive hinzufügen?

Ich habe eine sehr heruntergekommene Version von dem, was ich tue, die das Problem vermittelt.

Ich habe ein einfaches directive. Wenn Sie auf ein Element klicken, wird ein weiteres hinzugefügt. Es muss jedoch erst kompiliert werden, um es korrekt wiederzugeben.

Meine Forschung führte mich zu $compile. Aber alle Beispiele verwenden eine komplizierte Struktur, die ich hier nicht wirklich anwenden kann.

Geigen sind hier: http://jsfiddle.net/paulocoelho/fBjbP/1/

Und der JS ist hier:

var module = angular.module('testApp', [])
    .directive('test', function () {
    return {
        restrict: 'E',
        template: '<p>{{text}}</p>',
        scope: {
            text: '@text'
        },
        link:function(scope,element){
            $( element ).click(function(){
                // TODO: This does not do what it's supposed to :(
                $(this).parent().append("<test text='n'></test>");
            });
        }
    };
});

Lösung von Josh David Miller: http://jsfiddle.net/paulocoelho/fBjbP/2/

210
PCoelho

Sie haben eine Menge sinnloser jQuery, aber der $ compile-Dienst ist tatsächlich super einfach in diesem Fall:

.directive( 'test', function ( $compile ) {
  return {
    restrict: 'E',
    scope: { text: '@' },
    template: '<p ng-click="add()">{{text}}</p>',
    controller: function ( $scope, $element ) {
      $scope.add = function () {
        var el = $compile( "<test text='n'></test>" )( $scope );
        $element.parent().append( el );
      };
    }
  };
});

Sie werden feststellen, dass ich Ihre Richtlinie ebenfalls überarbeitet habe, um einige bewährte Methoden zu befolgen. Lassen Sie mich wissen, wenn Sie Fragen dazu haben.

256

Zusätzlich zum perfekten Riceball LEE-Beispiel für das Hinzufügen einer neuen Element-Direktive

newElement = $compile("<div my-directive='n'></div>")($scope)
$element.parent().append(newElement)

Das Hinzufügen eines neuen Attribut-Direktive zu einem existierenden Element könnte folgendermaßen erfolgen:

Angenommen, Sie möchten spontan my-directive Zum span -Element hinzufügen.

template: '<div>Hello <span>World</span></div>'

link: ($scope, $element, $attrs) ->

  span = $element.find('span').clone()
  span.attr('my-directive', 'my-directive')
  span = $compile(span)($scope)
  $element.find('span').replaceWith span

Ich hoffe, das hilft.

75
deadrunk

Das dynamische Hinzufügen von Direktiven zu angularjs hat zwei Stile:

Fügen Sie eine anglejs-Direktive in eine andere Direktive ein

  • einfügen eines neuen Elements (Direktive)
  • einfügen eines neuen Attributs (Direktive) in element

einfügen eines neuen Elements (Direktive)

es ist einfach. Und Sie können in "Link" oder "Kompilieren" verwenden.

var newElement = $compile( "<div my-diretive='n'></div>" )( $scope );
$element.parent().append( newElement );

einfügen eines neuen Attributs in ein Element

Es ist schwer und macht mir innerhalb von zwei Tagen Kopfschmerzen.

Die Verwendung von "$ compile" löst einen kritischen rekursiven Fehler aus !! Möglicherweise sollte die aktuelle Direktive ignoriert werden, wenn das Element neu kompiliert wird.

$element.$set("myDirective", "expression");
var newElement = $compile( $element )( $scope ); // critical recursive error.
var newElement = angular.copy(element);          // the same error too.
$element.replaceWith( newElement );

Also muss ich einen Weg finden, die Direktiven "Link" -Funktion zu nennen. Es ist sehr schwierig, die nützlichen Methoden zu finden, die sich tief in Verschlüssen verbergen.

compile: (tElement, tAttrs, transclude) ->
   links = []
   myDirectiveLink = $injector.get('myDirective'+'Directive')[0] #this is the way
   links.Push myDirectiveLink
   myAnotherDirectiveLink = ($scope, $element, attrs) ->
       #....
   links.Push myAnotherDirectiveLink
   return (scope, Elm, attrs, ctrl) ->
       for link in links
           link(scope, Elm, attrs, ctrl)       

Nun, es funktioniert gut.

45
Riceball LEE
function addAttr(scope, el, attrName, attrValue) {
  el.replaceWith($compile(el.clone().attr(attrName, attrValue))(scope));
}
9
user1212212

Die akzeptierte Antwort von Josh David Miller funktioniert hervorragend, wenn Sie versuchen, dynamisch eine Direktive hinzuzufügen, die ein Inline-template verwendet. Wenn Ihre Direktive jedoch templateUrl nutzt, funktioniert seine Antwort nicht. Folgendes hat bei mir funktioniert:

.directive('helperModal', [, "$compile", "$timeout", function ($compile, $timeout) {
    return {
        restrict: 'E',
        replace: true,
        scope: {}, 
        templateUrl: "app/views/modal.html",
        link: function (scope, element, attrs) {
            scope.modalTitle = attrs.modaltitle;
            scope.modalContentDirective = attrs.modalcontentdirective;
        },
        controller: function ($scope, $element, $attrs) {
            if ($attrs.modalcontentdirective != undefined && $attrs.modalcontentdirective != '') {
                var el = $compile($attrs.modalcontentdirective)($scope);
                $timeout(function () {
                    $scope.$digest();
                    $element.find('.modal-body').append(el);
                }, 0);
            }
        }
    }
}]);
5
ferics2

Josh David Miller ist richtig.

PCoelho, falls Sie sich fragen, was $compile hinter den Kulissen und wie die HTML-Ausgabe aus der Direktive generiert wird, sehen Sie sich unten an

Das $compile Service kompiliert das Fragment von HTML ("< test text='n' >< / test >") enthält die Direktive ("test" als Element) und erzeugt eine Funktion. Diese Funktion kann dann mit einem Gültigkeitsbereich ausgeführt werden, um die "HTML-Ausgabe von einer Direktive" zu erhalten.

var compileFunction = $compile("< test text='n' > < / test >");
var HtmlOutputFromDirective = compileFunction($scope);

Weitere Details mit vollständigen Codebeispielen finden Sie hier: http://www.learn-angularjs-apps-projects.com/AngularJs/dynamically-add-directives-in-angularjs

5
Danial Lokman

Inspiriert von vielen der vorherigen Antworten habe ich die folgende "Stroman" -Richtlinie entwickelt, die sich durch alle anderen Richtlinien ersetzen wird.

app.directive('stroman', function($compile) {
  return {
    link: function(scope, el, attrName) {
      var newElem = angular.element('<div></div>');
      // Copying all of the attributes
      for (let prop in attrName.$attr) {
        newElem.attr(prop, attrName[prop]);
      }
      el.replaceWith($compile(newElem)(scope)); // Replacing
    }
  };
});

Wichtig: Registrieren Sie die Anweisungen, die Sie mit restrict: 'C' Verwenden möchten. So was:

app.directive('my-directive', function() {
  return {
    restrict: 'C',
    template: 'Hi there',
  };
});

Sie können wie folgt verwenden:

<stroman class="my-directive other-class" randomProperty="8"></stroman>

Um dies zu bekommen:

<div class="my-directive other-class" randomProperty="8">Hi there</div>

Protip. Wenn Sie keine auf Klassen basierenden Direktiven verwenden möchten, können Sie '<div></div>' In etwas ändern, was Ihnen gefällt. Z.B. haben ein festes Attribut, das den Namen der gewünschten Direktive anstelle von class enthält.

4
Gábor Imre