Je veux créer un AlertFactory avec Angular.factory. J'ai défini un modèle HTML comme suit
var template = "<h1>{{title}}</h1>";
Le titre est fourni par le contrôleur d’appel et appliqué comme suit
var compiled = $compile(template)(scope);
body.append(compiled);
Alors, comment puis-je passer de la portée isolée du contrôleur à l’usine? J'utilise dans le code de suivi du contrôleur
AlertFactory.open($scope);
Mais $ scope est une variable d’étendue du contrôleur global. Je veux juste passer une petite portée pour l’usine avec juste la propriété du titre.
Merci.
Vous pouvez créer une nouvelle étendue manuellement.
Vous pouvez créer une nouvelle portée à partir de $rootScope
si vous l’injectez ou simplement à partir de la portée de votre contrôleur - cela ne devrait pas avoir d’importance puisque vous allez le rendre isolé.
var alertScope = $scope.$new(true);
alertScope.title = 'Hello';
AlertFactory.open(alertScope);
La clé ici passe true
à $new
, qui accepte un paramètre pour isolate
, ce qui évite d’hériter de la portée du parent.
Plus d'informations peuvent être trouvées à: http://docs.angularjs.org/api/ng.$rootScope.Scope#$new
Si vous avez seulement besoin d'interpoler des choses, utilisez le service $ interpolate au lieu de $ compile. Vous n'aurez alors pas besoin d'une portée:
myApp.factory('myService', function($interpolate) {
var template = "<h1>{{title}}</h1>";
var interpolateFn = $interpolate(template);
return {
open: function(title) {
var html = interpolateFn({ title: title });
console.log(html);
// append the html somewhere
}
}
});
Contrôleur de test:
function MyCtrl($scope, myService) {
myService.open('The Title');
}
vérifier mon plunkr. Je génère par programme une directive de widget avec une directive de rendu.
https://plnkr.co/edit/5T642U9AiPr6fJthbVpD?p=preview
angular
.module('app', [])
.controller('mainCtrl', $scope => $scope.x = 'test')
.directive('widget', widget)
.directive('render', render)
function widget() {
return {
template: '<div><input ng-model="stuff"/>I say {{stuff}}</div>'
}
}
function render($compile) {
return {
template: '<button ng-click="add()">{{name}}</button><hr/>',
link: linkFn
}
function linkFn(scope, elem, attr) {
scope.name = 'Add Widget';
scope.add = () => {
const newScope = scope.$new(true);
newScope.export = (data) => alert(data);
const templ = '<div>' +
'<widget></widget>' +
'<button ng-click="export(this.stuff)">Export</button>' +
'</div>';
const compiledTempl = $compile(templ)(newScope);
elem.append(compiledTempl);
}
}
}
Les étapes suivantes sont les suivantes:
var comiledHTML = angular.element(yourHTML);
var newScope = $rootScope.$new();
var linkFun = $compile(comiledHTML);
var finalTemplate = linkFun(newScope);
YourHTMLElemet.append(finalTemplate);
Je suppose que lorsque vous parlez d'une portée isolée, vous parlez d'une directive.
Voici un exemple de la façon de le faire. http://jsfiddle.net/rgaskill/PYhGb/
var app = angular.module('test',[]);
app.controller('TestCtrl', function ($scope) {
$scope.val = 'World';
});
app.factory('AlertFactory', function () {
return {
doWork: function(scope) {
scope.title = 'Fun';
//scope.title = scope.val; //notice val doesn't exist in this scope
}
};
});
app.controller('DirCtrl', function ($scope, AlertFactory) {
AlertFactory.doWork($scope);
});
app.directive('titleVal',function () {
return {
template: '<h1>Hello {{title}}</h1>',
restrict: 'E',
controller: 'DirCtrl',
scope: {
title: '='
},
link: function() {
}
};
});
Fondamentalement, attachez un contrôleur à une directive qui a défini une portée d'isolement. La portée injectée dans le contrôleur de directive sera une portée isolée. Dans le contrôleur de directive, vous pouvez injecter votre AlertFactory avec laquelle vous pouvez passer le scope isolate.