Pouvez-vous remplacer des modèles spécifiques dans AngularUI Bootstrap?

88

Je suis curieux de savoir s'il existe un moyen de remplacer des modèles uniques et spécifiques du fichier ui-bootstrap-tpls. La grande majorité des modèles par défaut répondent à mes besoins, mais j'aimerais en remplacer quelques-uns spécifiques sans passer par tout le processus de capture de tous les modèles par défaut et de les connecter à la version non-tpls.

Jeremy Privett
la source
1
Je me suis également retrouvé à décorer le $modalservice pour obtenir plus de configurabilité sans (espérons-le) créer trop de casse-tête de maintenance. $provide.decorator('$modal'... Dans mon cas, je ne voulais pas rendre l' modalWindowélément. Déjà. Je ne l'utilisais tout simplement pas, et c'était le mieux que je pouvais trouver. J'adorerais entendre une meilleure façon si quelqu'un l'a.
bodine

Réponses:

123

Oui, les directives de http://angular-ui.github.io/bootstrap sont hautement personnalisables et il est facile de remplacer l'un des modèles (et de toujours s'appuyer sur ceux par défaut pour les autres directives).

Il suffit de nourrir $templateCache, soit le nourrir directement (comme fait dans le ui-bootstrap-tplsfichier) ou - probablement plus simple - remplacer un modèle en utilisant la <script>directive ( doc ).

Un exemple artificiel où je change le modèle de l' alerte à échange xpour Closeest indiqué ci - dessous:

<!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 en direct: http://plnkr.co/edit/gyjVMBxa3fToYTFJtnij?p=preview

pkozlowski.opensource
la source
19
J'aime cette réponse. Je n'aime tout simplement pas le fait qu'il ne soit pas inclus dans la page de documentation de Angular UI et il m'a fallu un certain temps pour comprendre comment faire quelque chose d'aussi simple que de montrer un modal.
Tri Vuong
2
La documentation @BruceBanner et de solides exemples de travail sont les deux plus gros inconvénients de l'interface utilisateur angulaire. Le projet est génial mais il a besoin d'un tendre amour des développeurs.
Robin van Baalen
1
@RobinvanBaalen c'est une fonctionnalité angular-js (pas angular-ui), elle est déjà documentée dans la documentation officielle d'angular js
Vikki
Veuillez vérifier la réponse @JcT à propos de $ provide.decorator, car c'est le moyen angulaire (le bon moyen dans ce cas) de remplacer les modèles de directive. Et c'est assez simple. Le simple ajout / remplacement d'un modèle à $ templateCache n'est pas vraiment la meilleure pratique.
John Bernardsson
@John Je ne suis pas sûr d'où vous obtenez les choses "c'est la méthode angulaire (la bonne façon dans ce cas)" et "simplement ajouter / remplacer un modèle à $ templateCache n'est pas vraiment la meilleure pratique" mais comme une des méthodes angulaires- ui et angular mainteneurs Je peux vous assurer qu'il n'y a rien de mal à remplacer les modèles. Sauf si vous avez des problèmes spécifiques à partager ...
pkozlowski.opensource
79

En utilisant $provide.decorator

Utiliser $providepour décorer la directive évite d'avoir à jouer directement avec $templateCache.

Au lieu de cela, créez votre modèle externe html comme vous le feriez normalement, avec le nom que vous voulez, puis remplacez la directive templateUrlpour y pointer.

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

Fourche du plunkr de pkozlowski.opensource: http://plnkr.co/edit/RE9AvUwEmKmAzem9mfpI?p=preview

(Notez que vous devez ajouter le suffixe "Directive" au nom de la directive que vous souhaitez décorer. Ci-dessus, nous décorons la alertdirective de UI Bootstrap , nous utilisons donc le nom alertDirective.)

Comme vous pouvez souvent vouloir faire plus que simplement remplacer le templateUrl, cela fournit un bon point de départ pour étendre davantage la directive, par exemple en surchargeant / encapsulant le lien ou la fonction de compilation ( par exemple ).

JcT
la source
9
C'est la bonne solution et suit les meilleures pratiques angulaires. Vous ne devez JAMAIS utiliser de chaînes pour créer du HTML, ni l'inclure explicitement dans le fichier index.html où vous injectez des scripts tiers. Merci @JcT!
TommyMac
2
Salut, est alertDirectiveun mot-clé? si oui, à quoi sert le mot-clé Tabs? J'essaie de faire la même chose sur les onglets, mais j'ai parcouru alert.js et je ne vois pas où ils se trouvaient alertDirective.
codenamezero
4
L'angularjs $compileProviderattache un suffixe «Directive» au nom de votre directive lorsque vous l'enregistrez (le $filterProviderfait de même avec un suffixe «Filtre»); dans la plupart des cas, cela est invisible, mais lors de la décoration, vous devrez ajouter ce suffixe à la directive que vous avez l'intention de cibler. Par exemple, tabDirectiveou tabsetDirective, etc. Pas exactement clairement documenté nulle part que je pouvais trouver, mais est là une référence au comportement similaire pour $filterProviderau moins: docs.angularjs.org/api/ng/provider/$filterProvider
JCT
2
Merci beaucoup @JcT, une excellente réponse. C'est la bonne façon de procéder. Et, comme vous le dites, un bon point de départ pour la "décoration" des directives tierces :)
John Bernardsson
1
@ValeraTumash: Désolé pour la réponse tardive. Ouais, je pense que votre configuration va être écrasée; cependant, à partir d'Angular v1.3, je crois que vous pouvez fournir un function(element, attributes)à templateUrl. Vous pouvez l'utiliser pour un comportement dynamique (retournez la fonction templateUrl d'origine ou votre propre chaîne d'URL en fonction d'un attribut, etc.). Cependant, ui.bootstrap utilise désormais également cette même fonctionnalité pour vous permettre de fournir un template-urlattribut sur une directive, vous pouvez donc également l'utiliser si vous êtes heureux de fournir le chemin du modèle directement via l'attribut d'élément de directive.
JcT
27

La réponse de pkozlowski.opensource est vraiment utile et m'a beaucoup aidé! Je l'ai modifié dans ma condition pour avoir un seul fichier définissant tous mes remplacements de modèles angulaires et chargé le JS externe pour réduire la taille de la charge utile.

Pour ce faire, allez au bas du fichier js source angulaire ui-bootstrap (par exemple ui-bootstrap-tpls-0.6.0.js) et trouvez le modèle qui vous intéresse. Copiez le bloc entier qui définit le modèle et collez-le dans votre fichier JS de substitutions.

par exemple

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

Ensuite, incluez simplement votre fichier de remplacement après ui-bootstrap et vous obtiendrez le même résultat.

Version fourchue pkozlowski.opensource « s Plunk http://plnkr.co/edit/iF5xw2YTrQ0IAalAYiAg?p=preview

Matt Byrne
la source
1
J'utilise ce même modèle, et bien que cela fonctionne; Je souhaite vraiment qu'il y ait un meilleur moyen. Je pense que je préférerais la configuration au clobber.
bodine
7

Vous pouvez utiliser template-url="/app/.../_something.template.html"pour remplacer le modèle actuel pour cette directive.

(Fonctionne au moins dans Accordion Bootstrap.)

cramoisi
la source