Czy możesz zastąpić określone szablony w AngularUI Bootstrap?

88

Jestem ciekawy, czy istnieje sposób na zastąpienie pojedynczych, określonych szablonów z pliku ui-bootstrap-tpls. Zdecydowana większość domyślnych szablonów odpowiada moim potrzebom, ale jest kilka konkretnych, które chciałbym wymienić bez przechodzenia przez cały proces pobierania wszystkich domyślnych szablonów i podłączania ich do wersji innej niż tpls.

Jeremy Privett
źródło
1
Odkryłem również, że dekorowałem $modalusługę, aby uzyskać większą konfigurowalność bez (miejmy nadzieję) wywoływania zbyt dużego bólu głowy związanego z konserwacją. $provide.decorator('$modal'... W moim przypadku nie chciałem renderować modalWindowelementu. Zawsze. Po prostu go nie używałem i to było najlepsze, na co mogłem wymyślić. Chciałbym lepiej usłyszeć, gdyby ktoś to miał.
bodine

Odpowiedzi:

123

Tak, dyrektywy z http://angular-ui.github.io/bootstrap są wysoce konfigurowalne i łatwo jest zastąpić jeden z szablonów (i nadal polegać na domyślnych w przypadku innych dyrektyw).

Wystarczy karmić $templateCache, albo bezpośrednio (jak to zrobiono w ui-bootstrap-tplspliku), albo - prawdopodobnie prostsze - nadpisać szablon za pomocą <script>dyrektywy ( doc ).

Zmyślony przykład gdzie mam zmianę szablonu ALERT do zamiany xza Closeprzedstawiono poniżej:

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

Plunker na żywo: http://plnkr.co/edit/gyjVMBxa3fToYTFJtnij?p=preview

pkozlowski.opensource
źródło
19
Podoba mi się ta odpowiedź. Po prostu nie podoba mi się to, że nie ma go na stronie dokumentacji Angular UI i zajęło mi sporo czasu, zanim wymyśliłem, jak zrobić coś tak prostego, jak pokazanie modalu.
Tri Vuong,
2
@BruceBanner Dokumentacja i solidne przykłady działania to dwie największe wady Angular UI. Projekt jest świetny, ale wymaga słodkiej miłości dewelopera.
Robin van Baalen
1
@RobinvanBaalen to jest funkcja angular-js (nie angular-ui), jest już udokumentowana w oficjalnych dokumentach
angular
Sprawdź odpowiedź @JcT na temat $ include.decorator, ponieważ jest to metoda Angular (w tym przypadku dobry sposób) na przesłanianie szablonów dyrektyw. I to jest dość łatwe. Samo dodanie / nadpisanie szablonu do $ templateCache nie jest tak naprawdę najlepszą praktyką.
John Bernardsson
@John Nie jestem pewien, skąd bierzesz rzeczy „to jest sposób Angular (dobry sposób w tym przypadku)” i „po prostu dodanie / nadpisanie szablonu do $ templateCache nie jest tak naprawdę najlepszą praktyką”, ale jako jedną z metod kątowych Ui i opiekunowie kątów Mogę zapewnić, że nie ma nic złego w zastępowaniu szablonów. Chyba że masz konkretne problemy do udostępnienia ...
pkozlowski.opensource
79

Za pomocą $provide.decorator

Użycie $providedyrektywy do dekoracji pozwala uniknąć bezpośredniego bałaganu $templateCache.

Zamiast tego utwórz swój zewnętrzny szablon html, jak zwykle, z dowolną nazwą, a następnie nadpisz dyrektywy, templateUrlaby na to wskazać.

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;
    });
  }

Widelec plunkr pkozlowski.opensource: http://plnkr.co/edit/RE9AvUwEmKmAzem9mfpI?p=preview

(Zauważ, że musisz dodać przyrostek „Dyrektywa” do nazwy dyrektywy, którą chcesz ozdobić. Powyżej dekorujemy alertdyrektywę UI Bootstrap , więc używamy nazwy alertDirective).

Ponieważ często możesz chcieć zrobić coś więcej niż tylko nadpisać templateUrl, jest to dobry punkt wyjścia do dalszego rozszerzania dyrektywy, na przykład przez przesłonięcie / zawinięcie linku lub funkcji kompilującej ( na przykład ).

JcT
źródło
9
To jest poprawne rozwiązanie i jest zgodne z najlepszymi praktykami kątowymi. NIGDY nie powinieneś używać ciągów znaków do tworzenia kodu HTML, ani też nie musisz jawnie umieszczać go w pliku index.html, do którego wstrzykujesz skrypty stron trzecich. Dzięki @JcT!
TommyMac
2
Cześć, czy alertDirectiveto słowo kluczowe? jeśli tak, do czego służy słowo kluczowe Tabs? Próbuję zrobić coś podobnego na kartach, ale przejrzałem alert.js i nie widzę, gdzie się alertDirectivetam znajdują.
codenamezero
4
Angularjs $compileProviderdołącza sufiks „Dyrektywa” do nazwy Twojej dyrektywy podczas jej rejestracji ( $filterProviderpodobnie robi się z przyrostkiem „Filtr”); w większości celów jest to niewidoczne, ale podczas dekorowania musisz dodać ten przyrostek do dyrektywy, na którą zamierzasz celować. Na przykład, tabDirectivelub tabsetDirective, itd. Nie jest dokładnie udokumentowane w żadnym miejscu, które mogłem znaleźć, ale tutaj jest odniesienie do podobnego zachowania $filterProviderprzynajmniej dla: docs.angularjs.org/api/ng/provider/$filterProvider
JcT
2
Wielkie dzięki @JcT, świetna odpowiedź. To jest właściwa droga. I, jak mówisz, dobry punkt wyjścia do „dekoracji” dyrektyw innych firm :)
John Bernardsson
1
@ValeraTumash: Przepraszamy za spóźnioną odpowiedź. Tak, myślę, że twoja konfiguracja zostanie zbita; jednak od Angular v1.3 wierzę, że możesz dostarczyć function(element, attributes)do templateUrl. Możesz tego użyć do jakiegoś dynamicznego zachowania (zwróć oryginalną funkcję templateUrl lub własny ciąg adresu URL w zależności od atrybutu itp.). Jednak ui.bootstrap używa teraz również tej samej funkcjonalności, aby umożliwić Ci dostarczenie template-urlatrybutu w dyrektywie, więc możesz go również potencjalnie użyć, jeśli z przyjemnością podasz ścieżkę szablonu bezpośrednio przez atrybut elementu dyrektywy.
JcT
27

Odpowiedź z pkozlowski.opensource jest bardzo przydatna i bardzo mi pomogła! Poprawiłem go w moim stanie, aby mieć jeden plik definiujący wszystkie moje nadpisania szablonu kątowego i załadowałem zewnętrzny JS, aby zmniejszyć rozmiar ładunku.

Aby to zrobić, przejdź na dół pliku js z angular ui-bootstrap ui-bootstrap-tpls-0.6.0.jsi znajdź szablon, który Cię interesuje. Skopiuj cały blok, który definiuje szablon i wklej go do pliku JS nadpisań.

na przykład

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>");
}]);

Następnie po prostu dołącz plik przesłonięć po ui-bootstrap i osiągniesz ten sam wynik.

Rozwidlony wersja pkozlowski.opensource „s upadać http://plnkr.co/edit/iF5xw2YTrQ0IAalAYiAg?p=preview

Matt Byrne
źródło
1
Używam tego samego wzoru i chociaż działa; Naprawdę chciałbym, żeby był lepszy sposób. Myślę, że wolałbym konfigurację niż bicie.
bodine
7

Możesz użyć, template-url="/app/.../_something.template.html"aby zastąpić bieżący szablon tej dyrektywy.

(Działa przynajmniej w Accordion Bootstrap.)

karmazynowy
źródło