Можете ли вы переопределить определенные шаблоны в AngularUI Bootstrap?

88

Мне любопытно, есть ли способ переопределить отдельные конкретные шаблоны из файла ui-bootstrap-tpls. Подавляющее большинство шаблонов по умолчанию соответствуют моим потребностям, но есть пара конкретных, которые я хотел бы заменить, не проходя весь процесс захвата всех шаблонов по умолчанию и их подключения к версии без tpls.

Джереми Приветт
источник
1
Я также обнаружил, что украшаю $modalслужбу, чтобы получить больше возможностей настройки, не создавая (надеюсь) слишком большой головной боли при обслуживании. $provide.decorator('$modal'... В моем случае я не хотел отображать modalWindowэлемент. Когда-либо. Я просто не использовал его, и это было лучшее, что я мог придумать. Я хотел бы услышать лучший способ, если он у кого-нибудь есть.
bodine

Ответы:

123

Да, директивы из http://angular-ui.github.io/bootstrap легко настраиваются, и один из шаблонов легко переопределить (и по-прежнему полагаться на шаблоны по умолчанию для других директив).

Достаточно кормить $templateCacheлибо напрямую (как это сделано в ui-bootstrap-tplsфайле), либо - что, возможно, проще - переопределить шаблон с помощью <script>директивы ( doc ).

Надуманный пример , когда я меняю шаблон ALERT, чтобы своп 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

pkozlowski.opensource
источник
19
Мне нравится этот ответ. Мне просто не нравится тот факт, что он не включен на страницу документации Angular UI, и мне потребовалось довольно много времени, чтобы понять, как сделать что-то столь же простое, как отображение модального окна.
Три Вуонг
2
@BruceBanner Документация и надежные рабочие примеры - два самых больших недостатка пользовательского интерфейса Angular. Проект отличный, но он требует нежной нежной любви разработчиков.
Робин ван Баален,
1
@RobinvanBaalen, это функция angular-js (не angular-ui), она уже задокументирована в официальных документах angular js
vikki
Пожалуйста, проверьте ответ @JcT о $ provide.decorator, так как это способ Angular (в данном случае хороший способ) переопределить шаблоны директив. И это довольно просто. Простое добавление / переопределение шаблона в $ templateCache на самом деле не лучшая практика.
Джон Бернардссон
@John Я не уверен, откуда вы берете вещи «это способ Angular (в данном случае хороший способ)» и «просто добавление / переопределение шаблона в $ templateCache - не лучшая практика», а как один из angular- ui и разработчики angular, могу вас заверить, что нет ничего плохого в переопределении шаблонов. Если у вас нет особых проблем, которыми вы хотите поделиться ...
pkozlowski.opensource 01
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: http://plnkr.co/edit/RE9AvUwEmKmAzem9mfpI?p=preview

(Обратите внимание, что вы должны добавить суффикс «Directive» к имени директивы, которую собираетесь украсить. Выше мы украшаем alertдирективу UI Bootstrap , поэтому мы используем это имя alertDirective.)

Поскольку вы часто можете захотеть сделать больше, чем просто переопределить templateUrl, это обеспечивает хорошую отправную точку для дальнейшего расширения директивы, например, путем переопределения / переноса ссылки или функции компиляции ( например ).

JcT
источник
9
Это правильное решение, соответствующее лучшим практикам angular. Вы НИКОГДА не должны использовать строки для создания HTML, и вам не следует явно включать его в файл index.html, в который вы вставляете сторонние скрипты. Спасибо @JcT!
TommyMac
2
Привет, alertDirectiveэто ключевое слово? если да, то для чего это ключевое слово Tabs? Я пытаюсь сделать то же самое на вкладках, но я просмотрел alert.js и не вижу, где они alertDirectiveтам были.
codenamezero
4
Angularjs $compileProviderприкрепляет суффикс «Директива» к имени вашей директивы, когда вы ее регистрируете ( $filterProviderаналогично с суффиксом «Фильтр»); для большинства целей это невидимо, но при декорировании вам нужно добавить этот суффикс к директиве, на которую вы собираетесь ориентироваться. Например, tabDirectiveили tabsetDirectiveи т. Д. Не совсем четко документировано где-либо, что я мог найти, но вот ссылка на аналогичное поведение по $filterProviderкрайней мере для: docs.angularjs.org/api/ng/provider/$filterProvider
JcT
2
Большое спасибо @JcT, отличный ответ. Это правильный путь. И, как вы говорите, хорошая отправная точка для «украшения» директив сторонних разработчиков :)
Джон Бернардссон
1
@ValeraTumash: Извините за поздний ответ. Да, я думаю, ваш конфиг затерется; однако из Angular v1.3 я считаю, что вы можете указать function(element, attributes)в templateUrl. Вы можете использовать это для некоторого динамического поведения (вернуть исходную функцию templateUrl или вашу собственную строку URL-адреса в зависимости от атрибута и т. Д.). Однако ui.bootstrap теперь также использует ту же функциональность, чтобы позволить вам указать template-urlатрибут в директиве, поэтому вы также можете потенциально использовать это, если вы готовы предоставить путь к шаблону напрямую через атрибут элемента директивы.
JcT
27

Ответ от pkozlowski.opensource действительно полезен и очень мне помог! Я настроил его в своем условии, чтобы иметь один файл, определяющий все мои переопределения шаблонов angular, и загрузил внешний JS, чтобы уменьшить размер полезной нагрузки.

Для этого перейдите в конец исходного js-файла angular ui-bootstrap (например 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 «s бухнуться http://plnkr.co/edit/iF5xw2YTrQ0IAalAYiAg?p=preview

Мэтт Бирн
источник
1
Я использую тот же шаблон, и хотя он работает; Я действительно хочу, чтобы не было лучшего способа. Думаю, я предпочел бы настройку затиранию.
bodine
7

Вы можете использовать template-url="/app/.../_something.template.html"для переопределения текущего шаблона для этой директивы.

(Работает по крайней мере в Accordion Bootstrap.)

малиновый
источник