Angular Директива Различные шаблоны
У меня есть директива myDirective с переменным типом. Если я запустил <my-directive type="X">
, я хочу, чтобы директива использовала templateUrl: x-template.html.
Если я делаю <my-directive type="Y">
, я хочу, чтобы директива использовала templateUrl: y-template.html.
Это моя текущая директива.
app.directive('myDirective', function() {
var myDirective = {
templateUrl: 'X-template.html',
restrict: 'E',
scope: {
type: '='
},
};
return myDirective;
});
Я прочитал через stackoverflow и angular документацию, но не нашел ничего, что мне нужно.
Теперь я пытаюсь сделать что-то по строкам:
if ($scope.type === 'X') {
templateUrl: 'X-template.html',
}
else if ($scope.type === 'Y') {
templateUrl: 'Y-template.html',
}
Но не знаю, где это сделать.
Вы, ребята, знаете, возможно ли это и как?
Ответы
Ответ 1
Вы можете обойти эту проблему, используя ng-include
внутри compile
:
app.directive('myDirective', function() {
return {
restrict: 'E',
compile: function(element, attrs) {
element.append('<div ng-include="\'' + attrs.type + '-template.html\'"></div>');
}
}
});
fiddle
Ответ 2
Angular будет принимать функцию как шаблон, поэтому вы можете сделать что-то вроде этого:
.directive('myDirective', function () {
return {
templateUrl: function (tElement, tAttrs) {
if (tAttrs) {
if (tAttrs.type === 'X') {
return 'X-template.html';
}
if (tAttrs.type === 'Y') {
return 'Y-template.html';
}
}
}
}
});
Для получения дополнительной информации см. документацию для службы $compile.
Ответ 3
Если вы готовы жить на краю кровотока, опираясь на путь кода 1.1.x(обратите внимание на предупреждение, прикрепленное к каждой записи заметок 1.1.x, поэтому я не разбавляю этот ответ, повторяя его снова здесь), вам повезло - эта функция была добавлена только в версии 1.1.4 3 апреля. Вы можете найти примечания к выпуску для 1.1.4 здесь и функцию журнал задач включает тест Жасмин, который демонстрирует, как использовать новую функциональность.
Если вы более консервативны и используете версию 1.0.x, то вы не сможете сделать это так же легко, но это можно сделать. Решение Mark Rajcok похоже, что оно будет соответствовать вашим требованиям, как указано, но я бы просто добавил несколько дополнительных заметок:
- Помимо выпуска версии 1.1.4 директивы компиляции не поддерживают модификацию во время выполнения.
- Вы можете рассмотреть
replaceWith()
вместо append()
, поскольку <my-directive>
не является стандартным типом элемента HTML.
- Если ваши шаблоны X и Y содержат дополнительные директивы, я не думаю, что вы сможете легко передавать атрибуты на
<my-template>
до корневого элемента вашего шаблона.
- Директива с заменой: true передаст атрибуты из исходного элемента в свой заменяющий корень, но я не думаю, что
ngInclude
будет делать то же самое из host с корнем включенного шаблона.
- Я также напоминаю, что
ngInclude
не требует, чтобы его шаблон имел ровно один корневой элемент.
- Возможно, вы сохранили атрибуты для родителя-замены, используя
replaceWith()
вместо append()
и обернув тег <div ng-include="">
в <div></div>
. Внешний <div>
может содержать атрибуты и все равно будет доступен после того, как элемент <div ngInclude>
заменит себя загруженным контентом.
- Имейте в виду, что
ngInclude
создает новую область. Это подводит вас к мигающему желтому знаку клаксонов об опасностях примитивных моделей. Для получения дополнительной информации см. эту прекрасную страницу из Angular депо GitHub.
Я могу предложить другую альтернативу для версии 1.0.x, но она включает в себя довольно много кода. Это более тяжелая работа, но у нее есть потенциал не только для переключения между шаблонами, но и с полнофункциональными директивами. Более того, его поведение более динамично.
app.directive('myDirective', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'partials/directive/my-directive.html',
link: function(scope, element, attrs, ctrl) {
// You can do this with isolated scope as well of course.
scope.type = attrs.type;
}
}
);
мой-directive.js
<div ng-switch on="{{type}}">
<div ng-switch-where="X" ng-include="X-template.html"></div>
<div ng-switch-where="Y" ng-include="Y-template.html"></div>
</div>
мой-directive.html
Ответ 4
Я решаю эту проблему так:
app.directive("post", function ($templateCache, $compile) {
function getTemplate(mode) {
switch (mode) {
case "create":
return "createPost.html";
case "view":
return "viewPost.html";
case "delete":
return "deletePost.html";
}
}
var defaultMode = "view";
return {
scope: {},
restrict: "AE",
compile: function (elem, attrs, transclude) {
return function ($scope, $element, $attr) {
function updateTemplate() {
$element.html("");
$compile($templateCache.get(getTemplate($scope.mode)).trim())($scope, function (clonedElement, scope) {
clonedElement.appendTo($element);
});
}
$scope.mode = $attr.mode || defaultMode;
$scope.$watch("mode", updateTemplate);
}
}
}
});
Вероятно, это не лучший способ сделать это, но у меня нет дополнительных возможностей.
Ответ 5
Это моя версия для необязательного переопределения шаблона по умолчанию
templateUrl: function (elem, attrs) {
if (attrs.customTemplate) {
return '/path/to/components/tmpl/' + attrs.customTemplate + '.html';
} else {
return '/path/to/components/tmpl/directive.html';
}
}
например, по директиве
<div my-directive custom-template="custom"></div>
Ответ 6
Хорошо, это может помочь кому-то здесь: -)
Чтобы ввести пользовательский attr в вашу ссылку или функцию контроллера, используйте следующее.
Я сейчас работаю, но позже напишу скрипку, если у меня появится шанс: -)
.directive('yourDirective', function() {
return {
restrict: 'EA',
template: '<div></div>', // or use templateUrl with/without function
scope: {
myAttibute: '@myAttr' // adds myAttribute to the scope
},
link: function(scope) {
console.log(scope.myAttibute);
}
}
}
//HTML ""
//Консоль выведет "foo"