Warten Sie, bis Angular die Variable ausgewertet hat
Ich habe viel damit herumgespielt und konnte es auch mit der im Bereich definierten Variablen nicht "="
zum Laufen bringen. Hier sind drei Lösungen, abhängig von Ihrer Situation.
Lösung Nr. 1
Ich fand heraus, dass die Variable noch nicht durch Winkel bewertet wurde, als sie an die Direktive übergeben wurde. Dies bedeutet, dass Sie darauf zugreifen und es in der Vorlage verwenden können, jedoch nicht innerhalb der Link- oder App-Controller-Funktion, es sei denn, wir warten auf die Auswertung.
Wenn Ihre Variable zu ändern ist , oder abgerufen wird durch eine Anfrage, die Sie verwenden sollten $observe
oder $watch
:
app.directive('yourDirective', function () {
return {
restrict: 'A',
// NB: no isolated scope!!
link: function (scope, element, attrs) {
// observe changes in attribute - could also be scope.$watch
attrs.$observe('yourDirective', function (value) {
if (value) {
console.log(value);
// pass value to app controller
scope.variable = value;
}
});
},
// the variable is available in directive controller,
// and can be fetched as done in link function
controller: ['$scope', '$element', '$attrs',
function ($scope, $element, $attrs) {
// observe changes in attribute - could also be scope.$watch
$attrs.$observe('yourDirective', function (value) {
if (value) {
console.log(value);
// pass value to app controller
$scope.variable = value;
}
});
}
]
};
})
.controller('MyCtrl', ['$scope', function ($scope) {
// variable passed to app controller
$scope.$watch('variable', function (value) {
if (value) {
console.log(value);
}
});
}]);
Und hier ist das HTML (denken Sie an die Klammern!):
<div ng-controller="MyCtrl">
<div your-directive="{{ someObject.someVariable }}"></div>
<!-- use ng-bind in stead of {{ }}, when you can to avoids FOUC -->
<div ng-bind="variable"></div>
</div>
Beachten Sie, dass Sie die Variable nicht im Bereich festlegen sollten "="
, wenn Sie die $observe
Funktion verwenden. Außerdem habe ich festgestellt, dass Objekte als Zeichenfolgen übergeben werden. Wenn Sie also Objekte übergeben, verwenden Sie Lösung 2 oder scope.$watch(attrs.yourDirective, fn)
(oder 3, wenn sich Ihre Variable nicht ändert).
Lösung Nr. 2
Wenn Ihre Variable beispielsweise in einem anderen Controller erstellt wurde , Sie jedoch nur warten müssen, bis Angular sie ausgewertet hat, bevor Sie sie an den App-Controller senden, können Sie $timeout
warten, bis der $apply
ausgeführt wird. Außerdem müssen wir es verwenden $emit
, um es an den übergeordneten Bereichs-App-Controller zu senden (aufgrund des isolierten Bereichs in der Direktive):
app.directive('yourDirective', ['$timeout', function ($timeout) {
return {
restrict: 'A',
// NB: isolated scope!!
scope: {
yourDirective: '='
},
link: function (scope, element, attrs) {
// wait until after $apply
$timeout(function(){
console.log(scope.yourDirective);
// use scope.$emit to pass it to controller
scope.$emit('notification', scope.yourDirective);
});
},
// the variable is available in directive controller,
// and can be fetched as done in link function
controller: [ '$scope', function ($scope) {
// wait until after $apply
$timeout(function(){
console.log($scope.yourDirective);
// use $scope.$emit to pass it to controller
$scope.$emit('notification', scope.yourDirective);
});
}]
};
}])
.controller('MyCtrl', ['$scope', function ($scope) {
// variable passed to app controller
$scope.$on('notification', function (evt, value) {
console.log(value);
$scope.variable = value;
});
}]);
Und hier ist das HTML (keine Klammern!):
<div ng-controller="MyCtrl">
<div your-directive="someObject.someVariable"></div>
<!-- use ng-bind in stead of {{ }}, when you can to avoids FOUC -->
<div ng-bind="variable"></div>
</div>
Lösung Nr. 3
Wenn sich Ihre Variable nicht ändert und Sie sie in Ihrer Direktive auswerten müssen, können Sie die folgende $eval
Funktion verwenden:
app.directive('yourDirective', function () {
return {
restrict: 'A',
// NB: no isolated scope!!
link: function (scope, element, attrs) {
// executes the expression on the current scope returning the result
// and adds it to the scope
scope.variable = scope.$eval(attrs.yourDirective);
console.log(scope.variable);
},
// the variable is available in directive controller,
// and can be fetched as done in link function
controller: ['$scope', '$element', '$attrs',
function ($scope, $element, $attrs) {
// executes the expression on the current scope returning the result
// and adds it to the scope
scope.variable = scope.$eval($attrs.yourDirective);
console.log($scope.variable);
}
]
};
})
.controller('MyCtrl', ['$scope', function ($scope) {
// variable passed to app controller
$scope.$watch('variable', function (value) {
if (value) {
console.log(value);
}
});
}]);
Und hier ist das HTML (denken Sie an die Klammern!):
<div ng-controller="MyCtrl">
<div your-directive="{{ someObject.someVariable }}"></div>
<!-- use ng-bind instead of {{ }}, when you can to avoids FOUC -->
<div ng-bind="variable"></div>
</div>
Schauen Sie sich auch diese Antwort an: https://stackoverflow.com/a/12372494/1008519
Referenz für das FOUC-Problem (Flash of unstyled content): http://deansofer.com/posts/view/14/AngularJs-Tips-and-Tricks-UPDATED
Für Interessierte: Hier ist ein Artikel über den Winkellebenszyklus