AngularJS - Как я могу создать новую изолированную область программно?
Я хочу создать AlertFactory с помощью Angular.factory.
Я определил html-шаблон, например follow
var template = "<h1>{{title}}</h1>";
Название предоставляется вызовом контроллера и применяется следующим образом
var compiled = $compile(template)(scope);
body.append(compiled);
Итак, как я могу передать изолированную область от контроллера до factory?
Я использую в контроллере следующий код
AlertFactory.open($scope);
Но $scope - это переменная области глобального контроллера. Я просто хочу передать небольшую область для factory с единственным свойством title.
Спасибо.
Ответы
Ответ 1
Вы можете создать новую область вручную.
Вы можете создать новую область с $rootScope
, если вы ее введете или просто из области вашего контроллера - это не имеет значения, поскольку вы будете изолировать ее.
var alertScope = $scope.$new(true);
alertScope.title = 'Hello';
AlertFactory.open(alertScope);
Ключ здесь передается от true
до $new
, который принимает один параметр для isolate
, который позволяет избежать наследования области от родителя.
Более подробную информацию можно найти по адресу:
http://docs.angularjs.org/api/ng.$rootScope.Scope#$new
Ответ 2
Если вам нужно только интерполировать вещи, используйте $interpolate вместо $compile, и тогда вам не понадобится область действия:
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
}
}
});
Контроллер тестирования:
function MyCtrl($scope, myService) {
myService.open('The Title');
}
Fiddle
Ответ 3
Следующими являются следующие шаги:
- Добавьте свой HTML в DOM с помощью
var comiledHTML =
angular.element(yourHTML);
- Создайте новый масштаб, если хотите
var newScope = $rootScope.$new();
- Вызов $comile(); функция, которая возвращает функцию связи
var linkFun =
$compile(comiledHTML);
- Привязать новую область, вызывая linkFun
var finalTemplate =
linkFun(newScope);
- Добавить finalTemplate в DOM
YourHTMLElemet.append(finalTemplate);
Ответ 4
проверить мой plunkr. Я программно создаю директиву виджета с директивой рендеринга.
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);
}
}
}
Ответ 5
Я предполагаю, что когда вы говорите об области выделения, вы говорите о директиве.
Вот пример того, как это сделать.
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() {
}
};
});
В принципе, присоедините контроллер к директиве, которая определила область изоляции. Объем, введенный в директивный контроллер, будет областью выделения. В контроллере директивы вы можете ввести свой AlertFactory, с которым вы можете передать область изоляции.