Angular.js 指令动态模板URL
Posted
技术标签:
【中文标题】Angular.js 指令动态模板URL【英文标题】:Angular.js directive dynamic templateURL 【发布时间】: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.html
、before-2-tuesday.html
、...的文件
【问题讨论】:
Dynamic templateUrl - AngularJS 的可能重复项 如果您使用的是 AngularJS 1.5+,请查看这个优雅的解决方案:***.com/a/41743424/1274852 【参考方案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. 中发布的方式声明指令,则使用多个 <hymn ...>
时的用例应该可以正常工作。或者也许是时候在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。 <script type="text/ng-template" id="...">
- 是 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>'
)
【讨论】:
以上是关于Angular.js 指令动态模板URL的主要内容,如果未能解决你的问题,请参考以下文章