Подтвердить что ты не робот

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',
}

Но не знаю, где это сделать.

Вы, ребята, знаете, возможно ли это и как?

4b9b3361

Ответ 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"