2

Я понимаю, что я могу динамически установить templateUrl базу по опциону DOM атрибут template-url="foo.html" дал следующий код:Угловой: получить URL шаблона из родительской директивы

angular.module('foo').directive('parent', function() { 
    return { 
     restrict: 'E', 
     link: function(scope, element, attrs) { 
      // code 
     }, 
     templateUrl: function(elem,attrs) { 
      return attrs.templateUrl || 'some/path/default.html' 
     } 
    } 
}); 

Однако, мне нужно принять это шаг вперед и передайте эту строку на один уровень глубже, до детской директивы.

Учитывая этот HTML:

Использование в главном проекте

<parent parent-template="bar.html" child-template="foo.html"></parent>

Ребенок не будет подвергаться в большинстве случаев, так что если child-template установлен, он должен неявно заменить templateUrl для все дочерние элементы <child></child>, которые находятся в родительском foo.html.

Атрибут require: '^parent' передает данные из области действия в область видимости, но я не вижу этого в templateUrl, когда он объявлен.

foo.html

<h1>Title</h1> 
<child ng-repeat="item in array"></child> 

Директивы

angular.module('foo').directive('parent', function() { 
    return { 
     restrict: 'E', 
     link: function(scope, element, attrs) { 
      // code 
     }, 
     templateUrl: function(elem,attrs) { 
      return attrs.parentTemplate || 'some/path/default.html' 
     }, 
     scope: { 
      childTemplate: '=childTemplate' 
     } 
    } 
}) 
.directive('child', function() { 
    return { 
     restrict: 'E', 
     link: function(scope, element, attrs) { 
      // code 
     }, 
     templateUrl: function(elem,attrs) { 
      return ??? // parent.attribute.childTemplate? || 'some/path/default.html' 
     }, 
     require: '^parent', 
     scope: { 
      childTemplate: '=childTemplate' 
     } 
    } 
}); 
+1

Я просто с ума правку в код, пожалуйста, убедитесь, что я изменил правильно (вы назвали вторую директиву 'parent', так же, как и первый, я думаю, что ты хотел, чтобы называться' child'). Благодаря! – Josep

+0

Это правильно.Скопируйте/вставьте ошибку, спасибо! – Brian

+0

Возможно ли, что 'childTemplate', прикрепленный к области директивы' child', перезаписывает родительский? – dopatraman

ответ

1

Update

старый ответ (см ниже) не будет работать, потому что это возможно только для доступа к контроллеру необходимых директив внутри функций link, а templateUrl функция выполняется до функций link.

Таким образом, единственный способ решить эту проблему - обработать все функции templateUrl дочерней директивы. Однако this function only takes 2 arguments: tElement and tArgs.

Итак, нам нужно будет найти элемент родительской директивы и получить доступ к атрибуту child-template. Как это:

angular.module('testApp', []) 
.directive('parent', function() { 
    return { 
     restrict: 'E', 
     link: function(scope, element, attrs) { 
     }, 
     transclude:true, 
     templateUrl: function(elem,attrs) { 
      return attrs.parentTemplate || 'default.html' 
     } 
    } 
}) 
.directive('child', function() { 
    return { 
     restrict: 'E', 
     require:'^parent', 
     templateUrl: function(elem,attrs) { 
      //if jQuery is loaded the elem will be a jQuery element, so we can use the function "closest" 
      if(elem.closest) 
       return elem.closest("parent").attr("child-template") || 'default.html'; 

      //if jQuery isn't loaded we will have to do it manually 
      var parentDirectiveElem=elem; 
      do{ 
      parentDirectiveElem=parentDirectiveElem.parent(); 
      }while(parentDirectiveElem.length>0 && parentDirectiveElem[0].tagName.toUpperCase()!="PARENT"); 
      return parentDirectiveElem.attr("child-template") || 'default.html'; 
     } 
    } 
}); 

Example

Старый Ответ

Поскольку вы изолируют сферу, вы могли бы попробовать это, это немного Hacky, но я предполагаю, что это должно работать:

angular.module('foo').directive('parent', function() { 
    return { 
     restrict: 'E', 
     controller: function($scope) { 
      this.childTemplate=$scope.childTemplate; 
     }, 
     link: function(scope, element, attrs) { 

     },  
     templateUrl: function(elem,attrs) { 
      return attrs.parentTemplate || 'some/path/default.html' 
     }, 
     scope: { 
      childTemplate: '@' 
     } 
    } 
}) 
.directive('child', function() { 
    return { 
     restrict: 'E', 
     require: '^parent', 
     link: function(scope, element, attrs, parentController) { 
      if(parentController.childTemplate) 
       element.data("childTemplate", parentController.childTemplate); 
     }, 
     templateUrl: function(elem,attrs) { 
      return elem.data("childTemplate") || 'some/path/default.html' 
     } 
    } 
}); 
+0

Вам может понадобиться '$ watch'' childTemplate' дочерней директивы для этого. – dopatraman

+0

@ dopatraman из родительской директивы, которую вы имеете в виду, правильно? да, это хорошая идея, я собираюсь обновить код. Спасибо за ответ! – Josep

+0

@dopatraman Я обновил код, но проблема в том, что если значение атрибута 'childTemplate' изменяется в родительском, то я могу следить за этим изменением и обновлять контроллер ... Тем не менее, у ребенка I не может добавить наблюдателя, потому что свойство установлено в контроллере родителя, и у вас могут быть только наблюдатели в области ... Возможно, я мог бы попробовать наблюдать, но это кажется слишком большим, поэтому я думаю, что я будет проходить, так как кажется маловероятным, что они захотят это объяснить. – Josep

0

В моем вопросе я пытался обеспечить переопределение для templateUrl готовой директивы, у которой ее не было. Мой оригинальный вопрос не упоминает об этом, однако я хотел добавить это как ссылку на других, которые, возможно, забыли, как и я. Angular позволяет вам украшать директивы и переопределять их свойства.

app.config(function($provide) { 
    $provide.decorator('child', function($delegate) { 
    var directive = $delegate[0]; 

    directive.templateUrl = 'path/to/custom.html'; 
    return $delegate; 
    }); 
}); 
Смежные вопросы