你可以覆盖 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 与“过滤器”后缀类似);在大多数情况下,这是不可见的,但在装饰时,您需要将此后缀附加到您打算定位的指令中。例如,tabDirectivetabsetDirective 等。在我能找到的任何地方都没有完全清楚地记录在案,但这里至少引用了 $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

AngularUI Modal - 防止身体移位和滚动

Angular UI-Bootstrap 弹出框可拖动

与 Bootstrap 模态一起使用时显示在模态后面的 Angular ui-select 选项

5款最好用的AngularJS程序构建框架