web-dev-qa-db-de.com

AngularJS-Direktiven weisen den Zugriff von der Steuerung aus zu

Ich versuche, auf die Attribute einer Direktive in der Controller-Funktion zuzugreifen. Als ich darauf zugreife, ist es jedoch undefiniert. Mir ist aufgefallen, dass ein einfacher Timer funktioniert. Gibt es eine Möglichkeit, Code erst auszuführen, nachdem die Direktive und ihre Gültigkeitsbereiche bereit und für die Verwendung eingestellt sind?

Ich habe damit herumgespielt. Stellen Sie sicher, dass Ihre Konsole geöffnet ist. http://jsfiddle.net/paulocoelho/uKA2L/1/

Hier ist der Code, den ich in der Geige verwende:

<div ng-app="testApp" >
    <testcomponent text="hello!"></testcomponent>
</div>
var module = angular.module('testApp', [])
    .directive('testcomponent', function () {
    return {
        restrict: 'E',
        template: '<div><p>{{text}} This will run fine! </p></div>',
        scope: {
            text: '@text'
        },
        controller: function ($scope, $element) {
            console.log($scope.text); // this will return undefined
            setTimeout(function () {
                console.log($scope.text);    // this will return the actual value...
            }, 1000);
        },
        link: function ($scope, $element, $attrs) {
            console.log($scope.text);
            setTimeout(function () {
                console.log($scope.text);
            }, 1000);
        }
    };
});
37
PCoelho

Was funktioniert ist, wenn Sie einstellen

scope.text = $attrs.text;

innerhalb der Verknüpfung und der Controller-Funktionen. Dies funktioniert nur anfangs, da keine 2-Wege-Datenbindung vorhanden ist. Sie können jedoch $ attrs.observe verwenden.

Siehe fiddle: http://jsfiddle.net/JohannesJo/nm3FL/2/

27

In einem isolierten Bereich kann in der Verknüpfungsfunktion nicht auf eine mit '@' definierte lokale Bereichseigenschaft zugegriffen werden. Wie @remigio bereits erwähnte, sind solche lokalen Bereichseigenschaften zu diesem Zeitpunkt undefined. $ attrs. $ observ () oder $ scope. $ watch () müssen verwendet werden, um den (interpolierten) Wert asynchron zu erhalten.

Wenn Sie im Attribut einen konstanten Wert übergeben (d. H. Keine Interpolation erforderlich, d. H. Der Wert des Attributs enthält keine {{}}), ist kein '@' oder $ observer oder $ watch erforderlich. Sie können $ attrs verwenden.attribute_name einmal, wie @hugo vorschlägt, oder wenn Sie eine Zahl oder einen Booleschen Wert übergeben und den richtigen Typ erhalten möchten, können Sie $ scope. $ eval ($ attrs.attribute_name) Einmal.

Wenn Sie '=' verwenden, um eine lokale Bereichseigenschaft an eine übergeordnete Bereichseigenschaft zu binden, steht der Wert der Eigenschaft in der Verknüpfungsfunktion zur Verfügung ($ observ oder $ watch oder $ eval sind nicht erforderlich).

25
Mark Rajcok

Seit Angular 1.3 können Sie bindToController verwenden. Hier ist ein Beispiel, wie ich es verwende. Hier füge ich das Attribut zu scope hinzu und verwende dann bindToController um das im controller zu benutzen:

var module = angular.module('testApp', [])
    .directive('testcomponent', function () {
    return {
        restrict: 'E',
        template: '<div><p>{{text}} This will run fine! </p></div>',
        scope: {
            text: '@text'
        },
        controller: function () {
            console.log(this.text);
        },
        controllerAs: 'vm',
        bindToController: true
    };
});

Angular 1.3 führt eine neue Eigenschaft in das Direktivendefinitionsobjekt bindToController ein, die genau das tut, was es sagt. Bei Festlegung auf true in einer Direktive mit isoliertem Bereich, die ControllerAs verwendet, sind die Eigenschaften der Komponente eher an den Controller als an den Bereich gebunden. Das heißt, Angular stellt sicher, dass beim Instanziieren des Controllers die Anfangswerte der isolierten Gültigkeitsbereichsbindungen verfügbar sind und zukünftige Änderungen ebenfalls automatisch verfügbar sind.

8
Neel

Verwenden Sie stattdessen $scope Um den Wert der Direktivenattribute zu erhalten, bevorzuge ich persönlich die Verwendung von $attrs für die Funktion controller oder nur attrs am 3. Parameter der Funktion link. Ich habe kein Problem, wenn ich den Attributwert von einem controller mit folgendem Code ohne Zeitlimit erhalte:

var module = angular.module('testApp', [])
    .directive('testcomponent', function () {
    return {
    restrict: 'E',
    template: '<div><p>{{text}} This will run fine! </p></div>',
    scope: {
        text: '@text'
    },
    controller: ['$scope','$attrs', function ($scope, $attrs) {
        console.log($attrs.text); // just call to the $attrs instead $scope and i got the actual value
        $scope.text = $attrs.text; //assign attribute to the scope
    }]
    };
});
6
Bayu

Die Verknüpfungsfunktion wird vor der $ digest-Schleife aufgerufen, in diesem Moment sind Bereichsvariablen undefiniert. Schauen Sie sich dieses Kapitel und dieses andere an, um zu verstehen, wie die Verknüpfungsfunktion funktioniert. Sie verwenden die Link-Funktion nur zum Definieren von Überwachungen und/oder Verhaltensweisen für die Direktive, nicht zum Manipulieren des Modells. Dies erfolgt in Controllern.

1
remigio

Wenn Sie über Ihre Direktive auf diesen Wert zugreifen, um ihn mit einer Direktive in Ihre Ansicht einzufügen, können Sie über die API $ compile auf dieses Attribut zugreifen und so etwas tun

var string = "<div> " + scope.text + "</div>";
$compile(string)(scope, function(cloned, scope){
       element.append(cloned);
});
0
cuterthanbacon