【问题标题】:Angular.js directive dynamic templateURLAngular.js 指令动态模板URL
【发布时间】:2014-03-17 03:01:50
【问题描述】:

我在 routeProvider 模板中有一个自定义标签,它需要 directive 模板。 version 属性将由作用域填充,然后调用正确的模板。

<hymn ver="before-{{ week }}-{{ day }}"></hymn>

根据星期几和星期几,有多种版本的赞美诗。我期待使用该指令来填充正确的.html 部分。 templateUrl 没有读取该变量。

emanuel.directive('hymn', function() {
    var contentUrl;
    return {
        restrict: 'E',
        link: function(scope, element, attrs) {
            // concatenating the directory to the ver attr to select the correct excerpt for the day
            contentUrl = 'content/excerpts/hymn-' + attrs.ver + '.html';
        },
        // passing in contentUrl variable
        templateUrl: contentUrl
    }
});

excerpts 目录中有多个标记为before-1-monday.htmlbefore-2-tuesday.html、...的文件

【问题讨论】:

标签: angularjs angularjs-directive


【解决方案1】:
emanuel.directive('hymn', function() {
   return {
       restrict: 'E',
       link: function(scope, element, attrs) {
           // some ode
       },
       templateUrl: function(elem,attrs) {
           return attrs.templateUrl || 'some/path/default.html'
       }
   }
});

所以你可以通过标记提供 templateUrl

<hymn template-url="contentUrl"><hymn>

现在您只需注意属性 contentUrl 会填充动态生成的路径。

【讨论】:

  • 很好,但是...我可以从 templateUrl 函数访问范围属性吗? templateUrl 取决于范围值,但我无法访问它:(
  • 很高兴您找到了解决方案。我不建议指令依赖于其父指令,除非它是在指令的 require 部分中设置的控制器。
  • 终于!正是我想要的!我没有意识到我可以从 templateUrl 函数访问 elem 和 attrs 。谢谢!
  • templateUrl 每个指令被调用一次,它不是在每个指令实例初始化时被调用,小心!!!虽然它可能是角度的错误......
  • 我还没有检查过,但根据我的最新发现,可能值得一提的是它是once per $compile phase。换句话说,如果您将ng-repeat 与您的指令一起使用,并希望根据特定的ng-repeat 项目上下文设置单独的模板,它将不起作用,因为$compile 阶段在实际ng-repeat 发生之前遍历您的指令一次。所以在这个意义上它被称为一次......
【解决方案2】:

您可以使用ng-include 指令。

试试这样的:

emanuel.directive('hymn', function() {
   return {
       restrict: 'E',
       link: function(scope, element, attrs) {
           scope.getContentUrl = function() {
                return 'content/excerpts/hymn-' + attrs.ver + '.html';
           }
       },
       template: '<div ng-include="getContentUrl()"></div>'
   }
});

UPD。用于观看ver属性

emanuel.directive('hymn', function() {
   return {
       restrict: 'E',
       link: function(scope, element, attrs) {
           scope.contentUrl = 'content/excerpts/hymn-' + attrs.ver + '.html';
           attrs.$observe("ver",function(v){
               scope.contentUrl = 'content/excerpts/hymn-' + v + '.html';
           });
       },
       template: '<div ng-include="contentUrl"></div>'
   }
});

【讨论】:

  • 它的绝佳解决方案。有没有办法编写它可以处理多个实例?目前,一旦设置了范围,它就无法识别新的 attrs.ver。
  • 你的意思是,你想看ver的属性变化和重新渲染指令?
  • 感谢您的澄清。如果您以 upd. 中发布的方式声明指令,则使用多个 &lt;hymn ...&gt; 时的用例应该可以正常工作。或者也许是时候在jsfilddle 构建原型了?
  • 您好 @AlenGiliana,Ive take a look at your site, and changed [JSFiddle](http://jsfiddle.net/JQgG5/6/). All you need is scope:{}` 在指令声明中 - scope isolation。此外,我强烈建议您使用最新版本的 angular。 &lt;script type="text/ng-template" id="..."&gt; - 是 html 页面的本地替代品
  • 您的意思是使用 Angular 1.2.1 吗?顺便谢谢你的帮助,这个学习曲线太疯狂了:)
【解决方案3】:

感谢@pgregory,我可以使用此指令进行内联编辑来解决我的问题

.directive("superEdit", function($compile){
    return{
        link: function(scope, element, attrs){
            var colName = attrs["superEdit"];
            alert(colName);

            scope.getContentUrl = function() {
                if (colName == 'Something') {
                    return 'app/correction/templates/lov-edit.html';
                }else {
                    return 'app/correction/templates/simple-edit.html';
                }
            }

            var template = '<div ng-include="getContentUrl()"></div>';

            var linkFn = $compile(template);
            var content = linkFn(scope);
            element.append(content);
        }
    }
})

【讨论】:

    【解决方案4】:

    这里不需要自定义指令。只需使用ng-include src 属性。它已编译,因此您可以将代码放入其中。 See plunker with solution for your issue.

    <div ng-repeat="week in [1,2]">
      <div ng-repeat="day in ['monday', 'tuesday']">
        <ng-include src="'content/before-'+ week + '-' + day + '.html'"></ng-include>
      </div>
    </div>
    

    【讨论】:

      【解决方案5】:

      我遇到了同样的问题,但我以与其他人略有不同的方式解决了问题。 我正在使用角度 1.4.4。

      在我的例子中,我有一个创建 CSS Bootstrap 面板的 shell 模板:

      <div class="class-container panel panel-info">
          <div class="panel-heading">
              <h3 class="panel-title">{{title}} </h3>
          </div>
          <div class="panel-body">
              <sp-panel-body panelbodytpl="{{panelbodytpl}}"></sp-panel-body>
          </div>
      </div>
      

      我想根据路线包含面板正文模板。

          angular.module('MyApp')
          .directive('spPanelBody', ['$compile', function($compile){
              return {
                  restrict        : 'E',
                  scope : true,
                  link: function (scope, element, attrs) {
                      scope.data = angular.fromJson(scope.data);
                      element.append($compile('<ng-include src="\'' + scope.panelbodytpl + '\'"></ng-include>')(scope));
                  }
              }
          }]);
      

      当路由为#/students 时,我将包含以下模板:

      <div class="students-wrapper">
          <div ng-controller="StudentsIndexController as studentCtrl" class="row">
              <div ng-repeat="student in studentCtrl.students" class="col-sm-6 col-md-4 col-lg-3">
                  <sp-panel 
                  title="{{student.firstName}} {{student.middleName}} {{student.lastName}}"
                  panelbodytpl="{{'/student/panel-body.html'}}"
                  data="{{student}}"
                  ></sp-panel>
              </div>
          </div>
      </div>
      

      panel-body.html 模板如下:

      Date of Birth: {{data.dob * 1000 | date : 'dd MMM yyyy'}}
      

      在有人想要尝试的情况下的示例数据:

      var student = {
          'id'            : 1,
          'firstName'     : 'John',
          'middleName'    : '',
          'lastName'      : 'Smith',
          'dob'           : 1130799600,
          'current-class' : 5
      }
      

      【讨论】:

        【解决方案6】:

        我有一个关于这个的example

        <!DOCTYPE html>
        <html ng-app="app">
        
          <head>
            <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
          </head>
        
          <body>
            <div class="container-fluid body-content" ng-controller="formView">
                <div class="row">
                    <div class="col-md-12">
                        <h4>Register Form</h4>
                        <form class="form-horizontal" ng-submit="" name="f" novalidate>
                            <div ng-repeat="item in elements" class="form-group">
                                <label>{{item.Label}}</label>
                                <element type="{{item.Type}}" model="item"></element>
                            </div>
                            <input ng-show="f.$valid" type="submit" id="submit" value="Submit" class="" />
                        </form>
                    </div>
                </div>
            </div>
            <script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
            <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
            <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
            <script src="app.js"></script>
          </body>
        
        </html>
        

        angular.module('app', [])
            .controller('formView', function ($scope) {
                $scope.elements = [{
                    "Id":1,
                    "Type":"textbox",
                    "FormId":24,
                    "Label":"Name",
                    "PlaceHolder":"Place Holder Text",
                    "Max":20,
                    "Required":false,
                    "Options":null,
                    "SelectedOption":null
                  },
                  {
                    "Id":2,
                    "Type":"textarea",
                    "FormId":24,
                    "Label":"AD2",
                    "PlaceHolder":"Place Holder Text",
                    "Max":20,
                    "Required":true,
                    "Options":null,
                    "SelectedOption":null
                }];
            })
            .directive('element', function () {
                return {
                    restrict: 'E',
                    link: function (scope, element, attrs) {
                        scope.contentUrl = attrs.type + '.html';
                        attrs.$observe("ver", function (v) {
                            scope.contentUrl = v + '.html';
                        });
                    },
                    template: '<div ng-include="contentUrl"></div>'
                }
            })
        

        【讨论】:

          猜你喜欢
          • 2017-01-21
          • 1970-01-01
          • 2013-12-28
          • 2013-11-25
          • 1970-01-01
          • 1970-01-01
          • 2016-06-02
          • 2015-08-20
          • 1970-01-01
          相关资源
          最近更新 更多