Можете ли вы изменить templateUrl на лету?

Можно ли изменить templateUrl "на лету", передав значения в области действия? Я хочу передать данные контроллеру, который будет отображать страницу на основе данных, переданных из директивы

что-то может выглядеть так:

<div> 
   <boom data="{{myData}}" />
</div> 

.directive('boom', function {
        return {
            restrict: 'E',
            transclude: true,
            scope: 'isolate',
            locals: { data: 'bind' },
            templateUrl: "myTemplate({{boom}}})" // <- that of course won't work.
        }
    });

Ответ 1

Возможно, но когда ваш шаблон для загрузки зависит от некоторых данных области, вы больше не можете использовать свойство директивы templateUrl, и вы будете обязаны использовать API нижнего уровня, а именно $http и $compile.

Примерно то, что вам нужно сделать (возможно только в функции связывания), - это получить содержимое шаблона с помощью $http (не забудьте включить $templateCache!), а затем скомпилировать содержимое шаблона "вручную".

Казалось бы, это много, но на практике это довольно просто. Я бы предложил посмотреть на ngInclude директиву источники, где используется этот шаблон.

Вот скелет такой директивы:

app.directive('boom', function($http, $templateCache, $compile, $parse) {
        return {
            restrict: 'E',
            link: function(scope , iElement, iAttrs) {                            
              var boom = $parse(iAttrs.data)(scope);
              $http.get('myTemplate'+boom, {cache: $templateCache}).success(function(tplContent){
                iElement.replaceWith($compile(tplContent)(scope));                
              });              
            } 
        }
    });

предполагая, что он будет использоваться как <boom data='name'></boom>. Рабочий фрагмент здесь: http://plnkr.co/edit/TunwvhPPS6MdiJxpNBg8?p=preview

Обратите внимание, что я изменил оценку атрибутов с {{name}} на парсинг атрибутов, поскольку, вероятно, шаблон должен определяться только один раз в начале.

Ответ 2

Это новая функция в версиях Angular версии 1.1.4+, которую я только что узнал, если я использую текущую неустойчивую (1.1.5), вы можете передать функцию в шаблон url директивы. Второй параметр функции - это значение директивы атрибута, как показано ниже.

Вот ссылка на неопубликованные документы, показывающие официальные изменения.

Чтобы использовать partials/template1.html в качестве шаблона url из

Html:

<div sub_view="template1"></div>

Директива

.directive('subView', [()->
  restrict: 'A'
  # this requires at least angular 1.1.4 (currently unstable)
  templateUrl: (notsurewhatthisis, attr)->
    "partials/#{attr.subView}.html"
])

Ответ 3

Я немного изменил ответ от pkozlowski.opensource.

From:

var boom = $parse(iAttrs.data)(scope);

To:

var boom = scope.data.myData

Это сработало для меня, и возможно использовать

<boom data="{{myData}}" /> 

в директиве.

Ответ 4

У меня была аналогичная проблема

 return {
        restrict: 'AE',
        templateUrl: function(elm,attrs){return (attrs.scrolled='scrolled' ?'parts/scrolledNav.php':'parts/nav.php')},
        replace: true,

Ответ 5

Это последующий ответ, в котором рассматриваются некоторые проблемы с предыдущими ответами. Примечательно, что он будет только компилировать шаблоны один раз (что важно, если у вас их много на вашей странице, и он будет следить за изменениями в шаблоне после его привязки. Он также копирует класс и стиль из исходного элемента в шаблон (хотя и не очень элегантный способ angular делает внутренне, когда вы используете "replace: true". В отличие от текущего поддерживаемого метода w00 > для использования функции для шаблона или шаблонаUrl, вы можете использовать информацию об области, чтобы определить шаблон для нагрузки.

.directive('boom', ['$http', '$templateCache', '$compile', function ($http, $templateCache, $compile) {
    //create a cache of compiled templates so we only compile templates a single time.
    var cache= {};
    return {
        restrict: 'E',
        scope: {
            Template: '&template'
        },
        link: function (scope, element, attrs) {
            //since we are replacing the element, and we may need to do it again, we need
            //to keep a reference to the element that is currently in the DOM
            var currentElement = element;
            var attach = function (template) {
                if (cache[template]) {
                    //use a cloneAttachFn so that the link function will clone the compiled elment instead of reusing it
                    cache[template](scope, function (e) {
                        //copy class and style
                        e.attr('class', element.attr('class'));
                        e.attr('style', element.attr('style'));
                        //replace the element currently in the DOM
                        currentElement.replaceWith(e);
                        //set e as the element currently in the dom
                        currentElement = e;
                    });
                }
                else {
                    $http.get('/pathtotemplates/' + template + '.html', {
                        cache: $templateCache
                    }).success(function (content) {
                        cache[template] = $compile(content);
                        attach(template);
                    }).error(function (err) {
                        //this is something specific to my implementation that could be customized
                        if (template != 'default') {
                            attach('default');
                        }
                        //do some generic hard coded template
                    });
                }
            };

            scope.$watch("Template()", function (v, o) {
                if (v != o) {
                    attach(v);
                }
            });
            scope.$on('$destroy', function(){
                currentElement.remove();
            });
        }
    };
} ])

Ответ 6

Эти ответы хороши, но не профессиональны. Существует синтаксис использования templateUrl, который мы часто не используем. Это может быть функция, которая возвращает URL. Эта функция имеет некоторые аргументы. Если вы хотите больше здесь, это классная статья

http://www.w3docs.com/snippets/angularjs/dynamically-change-template-url-in-angularjs-directives.html