Existe-t-il un moyen d'ajouter un élément qui est une directive angulaire avec des méthodes jQuery telles que append()
et de laisser Angular compiler/lier pour que cela fonctionne comme si vous aviez inclus la directive au départ?
Exemple:
app.directive('myAngularDirective', [function () {
...
// Lots of stuff in here; works when used normally but not when added via jQuery
});
$("body").append("<my-angular-directive />");
Il ajoute actuellement un élément DOM vide appelé "my-angular-directive", mais Angular n'intervient pas pour faire sa magie.
La bonne façon d’aller est d’utiliser: $ compile et si votre directive renvoie: directive definition object
(ce qui est en fait la façon recommandée d’aller), vous pouvez alors appeler la fonction link
sur celle-ci (pour injecter scope
, par exemple) .
$('body').append($compile("<my-angular-directive />")(scope));
scope.$apply();
Un exemple complet, tiré de la documentation Angular :
// Angular boilerplate
var app = angular.module("myApp", []);
app.controller("MyCtrl", function($scope) {
$scope.content = {
label: "hello, world!",
};
});
// Wrap the example in a timeout so it doesn't get executed when Angular
// is first started.
setTimeout(function() {
// The new element to be added
var $div = $("<div ng-controller='MyCtrl'>new: {{content.label}}</div>");
// The parent of the new element
var $target = $("[ng-app]");
angular.element($target).injector().invoke(function($compile) {
var $scope = angular.element($target).scope();
$target.append($compile($div)($scope));
// Finally, refresh the watch expressions in the new element
$scope.$apply();
});
}, 100);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">old: {{content.label}}</div>
</div>
Idéalement, vous devriez éviter de le faire.
Cependant, si vraiment, vraiment, vraiment vous en avez besoin, vous pouvez alors injecter et utiliser le service $compile
suivi d'un element.append
.
Si votre directive n'a pas besoin d'accéder à une étendue spécifique, vous pouvez même affecter les services $compile
et $rootScope
à window
dans la fonction run
du module de votre application, puis les utiliser en dehors du contexte angulaire en créant un nouveau scope
($rootScope.new()
) et encapsulez l'ajout d'élément à l'aide de $rootScope.apply()
.
La réponse acceptée ne fournissait pas un exemple complet, en voici un:
https://codepen.io/rhinojosahdz/pen/ZpGLZG
<body ng-app="app" ng-controller="Ctrl1 as ctrl1">
</body>
<script>
angular.module('app',[])
.controller('Ctrl1', ['$scope', '$compile', function($scope, $compile){
var vm = this;
vm.x = 123;
$('body').append($compile("<hola x='ctrl1.x' />")($scope));
}])
.directive('hola', function(){
return {
template: '<div ng-click="vm.alertXFromGivenScope()">click me!</div>'
,scope: {
x : '='
}
,controller: function(){
var vm = this;
vm.alertXFromGivenScope = function(){
alert(vm.x);
};
}
,controllerAs: 'vm'
,bindToController: true
}
})
<script>
Vous voulez vraiment éviter de faire une requête si vous le pouvez, mais je me suis heurté à un problème similaire il n'y a pas si longtemps, voici ma question et la bonne réponse qui devrait pouvoir vous aider. La réponse courte utilise $ compile.
Essaye ça
angular.element($("#appendToDiv")).append($compile("<my-angular-directive />")($scope));