Attendez que angular ait évalué la variable
J'ai eu beaucoup de tripotages avec cela, et je n'ai pas pu le faire fonctionner même avec la variable définie avec "="
dans la portée. Voici trois solutions en fonction de votre situation.
Solution n ° 1
J'ai trouvé que la variable n'était pas encore évaluée par angulaire lorsqu'elle a été transmise à la directive. Cela signifie que vous pouvez y accéder et l'utiliser dans le modèle, mais pas à l'intérieur du lien ou de la fonction de contrôleur d'application, sauf si nous attendons qu'il soit évalué.
Si votre variable change ou est récupérée via une requête, vous devez utiliser $observe
ou $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);
}
});
}]);
Et voici le html (rappelez-vous les crochets!):
<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>
Notez que vous ne devez pas définir la variable "="
dans la portée, si vous utilisez la $observe
fonction. De plus, j'ai trouvé qu'il transmettait les objets sous forme de chaînes, donc si vous passez des objets, utilisez la solution n ° 2 ou scope.$watch(attrs.yourDirective, fn)
(, ou n ° 3 si votre variable ne change pas).
Solution n ° 2
Si votre variable est créée dans un autre contrôleur , par exemple , mais que vous avez juste besoin d'attendre que angular l'ait évaluée avant de l'envoyer au contrôleur d'application, nous pouvons utiliser $timeout
pour attendre que le $apply
soit exécuté. Nous devons également l'utiliser $emit
pour l'envoyer au contrôleur d'application de la portée parent (en raison de la portée isolée dans la directive):
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;
});
}]);
Et voici le html (sans crochets!):
<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>
Solution n ° 3
Si votre variable ne change pas et que vous devez l'évaluer dans votre directive, vous pouvez utiliser la $eval
fonction:
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);
}
});
}]);
Et voici le html (rappelez-vous les crochets!):
<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>
Jetez également un œil à cette réponse: https://stackoverflow.com/a/12372494/1008519
Référence pour le problème FOUC (flash of unstyled content): http://deansofer.com/posts/view/14/AngularJs-Tips-and-Tricks-UPDATED
Pour les intéressés: voici un article sur le cycle de vie angulaire