你可以覆盖 AngularUI Bootstrap 中的特定模板吗?
Posted
技术标签:
【中文标题】你可以覆盖 AngularUI Bootstrap 中的特定模板吗?【英文标题】:Can you override specific templates in AngularUI Bootstrap? 【发布时间】:2013-07-13 17:07:18 【问题描述】:我很好奇是否有一种方法可以覆盖 ui-bootstrap-tpls 文件中的单个特定模板。绝大多数默认模板都符合我的需求,但我想替换几个特定的模板,而无需经历获取所有默认模板并将它们连接到非 tpls 版本的整个过程。
【问题讨论】:
我还发现自己装饰了$modal
服务以获得更多的可配置性,而不会(希望)造成太多的维护问题。 $provide.decorator('$modal'
... 就我而言,我不想渲染 modalWindow
元素。曾经。我只是没有使用它,这是我能想到的最好的。如果有人有的话,我很想听听更好的方法。
【参考方案1】:
是的,来自http://angular-ui.github.io/bootstrap 的指令是高度可定制的,并且很容易覆盖其中一个模板(并且仍然依赖于其他指令的默认模板)。
提供$templateCache
就足够了,要么直接提供(如ui-bootstrap-tpls
文件中所做的那样),要么——可能更简单——使用<script>
指令覆盖模板(doc)。
我正在更改警报模板以将 x
替换为 Close
的人为示例如下所示:
<!doctype html>
<html ng-app="plunker">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.4.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
<script id="template/alert/alert.html" type="text/ng-template">
<div class='alert' ng-class='type && "alert-" + type'>
<button ng-show='closeable' type='button' class='close' ng-click='close()'>Close</button>
<div ng-transclude></div>
</div>
</script>
</head>
<body>
<div ng-controller="AlertDemoCtrl">
<alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">
alert.msg
</alert>
<button class='btn' ng-click="addAlert()">Add Alert</button>
</div>
</body>
</html>
现场直播:http://plnkr.co/edit/gyjVMBxa3fToYTFJtnij?p=preview
【讨论】:
我喜欢这个答案。我只是不喜欢它没有包含在 Angular UI 的文档页面中,我花了很长时间才弄清楚如何做一些像显示模态一样简单的事情。 @BruceBanner 文档和可靠的工作示例是 Angular UI 的两个最大缺点。这个项目很棒,但它需要一些甜蜜温柔的开发者爱。 @RobinvanBaalen 这是一个 angular-js 功能(不是 angular-ui),it's already documented in angular js's official docs 请检查@JcT 关于 $provide.decorator 的回答,因为这是覆盖指令模板的 Angular 方式(在这种情况下是好的方式)。这相当容易。仅向 $templateCache 添加/覆盖模板并不是最佳实践。 @John 我不确定你从哪里得到的东西“这是 Angular 的方式(在这种情况下是好的方式)”和“只是将模板添加/覆盖到 $templateCache 并不是最好的实践”,但作为 angular-ui 和 angular 维护者之一,我可以向您保证,覆盖模板没有任何问题。除非您有具体问题要分享...【参考方案2】:使用$provide.decorator
使用$provide
来装饰指令,避免了直接乱用$templateCache
。
相反,像往常一样创建您的外部模板 html,使用您喜欢的任何名称,然后覆盖指令的 templateUrl
以指向它。
angular.module('plunker', ['ui.bootstrap'])
.config(['$provide', Decorate]);
function Decorate($provide)
$provide.decorator('alertDirective', function($delegate)
var directive = $delegate[0];
directive.templateUrl = "alertOverride.tpl.html";
return $delegate;
);
pkozlowski.opensource 的 plunkr 的分叉:http://plnkr.co/edit/RE9AvUwEmKmAzem9mfpI?p=preview
(请注意,您必须在要装饰的指令名称后附加“指令”后缀。上面,我们正在装饰 UI Bootstrap 的 alert
指令,因此我们使用名称 alertDirective
。)
由于您可能经常想要做的不仅仅是覆盖templateUrl
,这为进一步扩展指令提供了一个很好的起点,例如通过覆盖/包装链接或编译函数(for example)。
【讨论】:
这是正确的解决方案,并遵循角度最佳实践。您永远不应该使用字符串来创建 HTML,也不应该将其显式包含在您注入第三方脚本的 index.html 文件中。谢谢@JcT! 嗨,alertDirective
是关键字吗?如果是,Tabs
的关键字是什么?我正在尝试在标签上做类似的事情,但我查看了 alert.js,我看不到他们在哪里有 alertDirective
。
angularjs $compileProvider
在您注册指令时将“指令”后缀附加到指令的名称($filterProvider
与“过滤器”后缀类似);在大多数情况下,这是不可见的,但在装饰时,您需要将此后缀附加到您打算定位的指令中。例如,tabDirective
或 tabsetDirective
等。在我能找到的任何地方都没有完全清楚地记录在案,但这里至少引用了 $filterProvider
的类似行为:docs.angularjs.org/api/ng/provider/$filterProvider
非常感谢@JcT,一个很好的答案。这是正确的方法。而且,正如您所说,这是“装饰”第 3 方指令的一个很好的起点:)
@ValeraTumash:抱歉回答晚了。是的,我认为您的配置会被破坏;但是,从 Angular v1.3 开始,我相信您可以向 templateUrl 提供 function(element, attributes)
。您可以将其用于某些动态行为(根据属性返回原始 templateUrl 函数或您自己的 url 字符串等)。但是,ui.bootstrap 现在也使用相同的功能让您在指令上提供 template-url
属性,因此如果您愿意通过指令元素属性直接提供模板路径,您也可以使用它。【参考方案3】:
pkozlowski.opensource 的回答非常有用,对我帮助很大!我在我的条件下对其进行了调整,让一个文件定义了我所有的角度模板覆盖并加载了外部 JS 以降低有效负载大小。
为此,请转到 angular ui-bootstrap 源 js 文件的底部(例如 ui-bootstrap-tpls-0.6.0.js
)并找到您感兴趣的模板。复制定义模板的整个块并将其粘贴到您的覆盖 JS文件。
例如
angular.module("template/alert/alert.html", []).run(["$templateCache", function($templateCache)
$templateCache.put("template/alert/alert.html",
" <div class='alert' ng-class='type && \"alert-\" + type'>\n" +
" <button ng-show='closeable' type='button' class='close' ng-click='close()'>Close</button>\n" +
" <div ng-transclude></div>\n" +
" </div>");
]);
然后只需在 ui-bootstrap 之后包含您的覆盖文件即可获得相同的结果。
pkozlowski.opensource 的 plunk http://plnkr.co/edit/iF5xw2YTrQ0IAalAYiAg?p=preview
的分叉版本【讨论】:
我使用相同的模式,虽然它有效;我真的希望有更好的方法。我想我更喜欢配置而不是破坏。【参考方案4】:您可以使用template-url="/app/.../_something.template.html"
覆盖该指令的当前模板。
(至少在 Accordion Bootstrap 中工作。)
【讨论】:
以上是关于你可以覆盖 AngularUI Bootstrap 中的特定模板吗?的主要内容,如果未能解决你的问题,请参考以下文章
使用 AngularUI Bootstrap 模态的 AngularJS 中的范围问题
AngularJS、AngularUi(引导程序)和 NgRoute