您可以覆盖AngularUI引导程序中的特定模板吗?


88

我很好奇是否有一种方法可以覆盖ui-bootstrap-tpls文件中的单个特定模板。绝大多数默认模板都可以满足我的需求,但是我想替换几个特定的​​模板,而无需完成获取所有默认模板并将它们连接到非tpls版本的整个过程。


1
我还发现自己对$modal服务进行了装饰,以获得更多的可配置性,而不会(希望)造成过多的维护麻烦。$provide.decorator('$modal'...就我而言,我不想渲染该modalWindow元素。曾经 我只是没有使用它,这是我能想到的最好的方法。如果有人有,我很想听听更好的方法。
bodine

Answers:


123

是的,来自http://angular-ui.github.io/bootstrap的指令是高度可定制的,并且很容易覆盖其中一个模板(其他模板仍然依赖默认模板)。

够喂 $templateCache,可以直接(如在ui-bootstrap-tpls文件中完成),或者-可能更简单-使用<script>指令(doc)覆盖模板。

一个人为更改的示例,其中我正在更改警报的模板以进行交换 xClose如下所示:

<!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


19
我喜欢这个答案。我只是不喜欢它没有包含在Angular UI的文档页面中这一事实,并且花了我相当长的时间来弄清楚如何做像显示模式一样简单的事情。
Tri Vuong 2013年

2
@BruceBanner文档和可靠的工作示例是Angular UI的两个最大缺点。这个项目很棒,但是需要开发商的甜蜜温柔。
罗宾·范·巴伦

1
@RobinvanBaalen这是angular-js功能(不是angular-ui),已经在angular js的官方文档中进行了记录
vikki 2014年

请检查有关$ provide.decorator的@JcT答案,因为这是覆盖指令模板的Angular方法(在这种情况下,是一种好方法)。这很容易。仅向$ templateCache添加/覆盖模板并不是真正的最佳实践。
John Bernardsson 2015年

@John,我不确定从哪里得到东西“这是Angular的方式(在这种情况下,这是一种好方法)”和“仅向$ templateCache添加/覆盖模板并不是真正的最佳实践”,但是作为angular- ui和angular维护者我可以向您保证,覆盖模板没有错。除非您有特定的问题要分享...
pkozlowski.opensource

79

使用 $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

(请注意,必须将'Directive'后缀附加到要装饰的指令名称上。上面,我们正在装饰UI Bootstrap的alert指令,因此我们使用该名称alertDirective。)

您可能经常想做的事情不仅仅是覆盖templateUrl,这为进一步扩展指令提供了一个很好的起点,例如,通过覆盖/包装链接或编译函数(例如)。


9
这是正确的解决方案,并且遵循最佳的做法。您永远不要使用字符串来创建HTML,也不必在注入第三方脚本的index.html文件中明确包含它。谢谢@JcT!
TommyMac

2
嗨,是alertDirective关键字吗?如果是,关键字是Tabs什么?我正在尝试在选项卡上执行类似的操作,但是我查看了alert.js,但看不到它们alertDirective在其中的位置。
codenamezero 2015年

4
$compileProvider当您注册指令时,angularjs 在指令名称后附加“指令”后缀($filterProvider与“过滤器”后缀类似);在大多数情况下,这是不可见的,但是在装饰时,您需要将此后缀附加到要定位的指令中。例如tabDirectivetabsetDirective,等等。在我能找到的任何地方,都没有明确记录,但这是对以下类似行为的引用$filterProvider至少:docs.angularjs.org/api/ng/provider/$filterProvider
JcT 2015年

2
非常感谢@JcT,一个很好的答案。这是正确的方法。而且,正如您所说,这是“装饰”第三方指令的一个很好的起点:)
John Bernardsson

1
@ValeraTumash:对不起,我迟到了。是的,我认为您的配置将会变得混乱。但是,我相信从Angular v1.3中可以function(element, attributes)为templateUrl 提供一个。您可以将其用于某些动态行为(根据属性返回原始templateUrl函数或您自己的url字符串,等等)。但是,ui.bootstrap现在也使用了相同的功能template-url,使您可以在指令上提供属性,因此,如果您愿意直接通过指令元素属性提供模板路径,则也可以使用该功能。
JcT

27

来自pkozlowski.opensource的答案非常有用,对我帮助很大!我根据情况对其进行了调整,以使它具有定义所有角度模板替代的单个文件,并加载了外部JS以减小有效负载大小。

为此,请转到有角度的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的普拉克 http://plnkr.co/edit/iF5xw2YTrQ0IAalAYiAg?p=preview


1
我使用相同的模式,尽管它可以工作;我真的希望有更好的方法。我想我更喜欢配置而不是破坏。
bodine

7

您可以使用 template-url="/app/.../_something.template.html"覆盖该指令的当前模板。

(至少在Accordion Bootstrap中有效。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.