Puoi sovrascrivere modelli specifici in AngularUI Bootstrap?


88

Sono curioso di sapere se c'è un modo per sovrascrivere singoli modelli specifici dal file ui-bootstrap-tpls. La stragrande maggioranza dei modelli predefiniti si adatta alle mie esigenze, ma ce ne sono un paio specifici che vorrei sostituire senza passare attraverso l'intero processo di acquisizione di tutti i modelli predefiniti e collegarli alla versione non tpls.


1
Mi sono anche ritrovato a decorare il $modalservizio per ottenere una maggiore configurabilità senza (si spera) creare troppi problemi di manutenzione. $provide.decorator('$modal'... Nel mio caso non volevo rendere l' modalWindowelemento. Mai. Semplicemente non lo stavo usando, e questo era il meglio che potessi inventare. Mi piacerebbe sentire un modo migliore se qualcuno ce l'ha.
bodine

Risposte:


123

Sì, direttive da http://angular-ui.github.io/bootstrap sono altamente personalizzabili ed è facile sovrascrivere uno dei modelli (e fare ancora affidamento su quelli predefiniti per altre direttive).

È sufficiente alimentare $templateCache, alimentandolo direttamente (come fatto nel ui-bootstrap-tplsfile) o - probabilmente più semplice - sovrascrivere un modello usando la <script>direttiva ( doc ).

Un esempio inventato dove sto cambiando modello di avviso di scambio xper Closeè la seguente:

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


19
Mi piace questa risposta. Semplicemente non mi piace il fatto che non sia incluso nella pagina della documentazione di Angular UI e mi ci è voluto un po 'per capire come fare qualcosa di semplice come mostrare un modale.
Tri Vuong

2
@BruceBanner Documentation e solidi esempi di lavoro sono i due maggiori difetti dell'interfaccia utente di Angular. Il progetto è fantastico ma ha bisogno di un tenero amore per gli sviluppatori.
Robin van Baalen

1
@RobinvanBaalen questa è una funzione angular-js (non angular-ui), è già documentata nei documenti ufficiali di
angular

Si prega di controllare la risposta @JcT su $ provide.decorator, poiché questo è il modo angolare (il modo migliore in questo caso) per sovrascrivere i modelli di direttiva. Ed è abbastanza facile. La semplice aggiunta / sovrascrittura di un modello a $ templateCache non è davvero la migliore pratica.
John Bernardsson

@ John non sono sicuro da dove si ottengono le cose "questo è il modo angolare (il modo migliore in questo caso)" e "semplicemente aggiungere / sovrascrivere un modello a $ templateCache non è davvero la migliore pratica" ma come uno di angular- ui e manutentori angolari Posso assicurarti che non c'è niente di sbagliato nell'override dei modelli. A meno che tu non abbia problemi specifici da condividere ...
pkozlowski.opensource

80

Utilizzando $provide.decorator

L'uso $provideper decorare la direttiva evita la necessità di scherzare direttamente con $templateCache.

Invece, crea il tuo modello html esterno come faresti normalmente, con il nome che preferisci, quindi sovrascrivi la direttiva templateUrlper puntarlo.

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

Fork del plunkr di pkozlowski.opensource: http://plnkr.co/edit/RE9AvUwEmKmAzem9mfpI?p=preview

(Tieni presente che devi aggiungere il suffisso "Directive" al nome della direttiva che intendi decorare. Sopra, stiamo decorando la alertdirettiva di Bootstrap dell'interfaccia utente , quindi usiamo il nomealertDirective .)

Poiché spesso potresti voler fare di più che sovrascrivere il templateUrl, questo fornisce un buon punto di partenza da cui estendere ulteriormente la direttiva, ad esempio sovrascrivendo / avvolgendo il link o compilando la funzione ( per esempio ).


9
Questa è la soluzione corretta e segue le migliori pratiche angolari. Non dovresti MAI usare stringhe per creare HTML, né dovresti includerlo esplicitamente nel file index.html in cui inserisci script di terze parti. Grazie @JcT!
TommyMac

2
Ciao, è alertDirectiveuna parola chiave? se sì, a cosa serve la parola chiave Tabs? Sto cercando di fare una cosa simile sulle schede, ma ho guardato attraverso alert.js e non vedo dove fossero alertDirectivelì.
codenamezero

4
L'angularjs $compileProviderallega un suffisso "Directive" al nome della tua direttiva quando la registri (lo $filterProviderfa in modo simile con un suffisso "Filter"); per la maggior parte degli scopi questo è invisibile, ma durante la decorazione dovrai aggiungere questo suffisso alla direttiva che intendi targetizzare. Ad esempio, tabDirectiveo tabsetDirective, ecc. Non esattamente documentato chiaramente da nessuna parte che ho potuto trovare, ma ecco un riferimento al comportamento simile $filterProvideralmeno per: docs.angularjs.org/api/ng/provider/$filterProvider
JcT

2
Grazie mille @JcT, un'ottima risposta. Questo è il modo corretto di procedere. E, come dici tu, un buon punto di partenza per "decorare" le direttive di terze parti :)
John Bernardsson

1
@ValeraTumash: ci scusiamo per il ritardo nella risposta. Sì, penso che la tua configurazione verrà distrutta; tuttavia, da Angular v1.3 credo che tu possa fornire un function(element, attributes)templateUrl. Potresti usarlo per alcuni comportamenti dinamici (restituisci la funzione templateUrl originale o la tua stringa di URL a seconda di un attributo, ecc.). Tuttavia, ui.bootstrap ora utilizza anche la stessa funzionalità per consentirti di fornire un template-urlattributo su una direttiva, quindi potresti anche utilizzarlo potenzialmente se sei felice di fornire il percorso del modello direttamente tramite l'attributo dell'elemento direttiva.
JcT

27

La risposta di pkozlowski.opensource è davvero utile e mi ha aiutato molto! L'ho ottimizzato nelle mie condizioni per avere un singolo file che definisce tutte le mie sostituzioni di modelli angolari e ho caricato il JS esterno per mantenere basse le dimensioni del payload.

Per fare ciò, vai alla fine del file js sorgente angolare ui-bootstrap (ad esempio ui-bootstrap-tpls-0.6.0.js) e trova il modello che ti interessa. Copia l'intero blocco che definisce il modello e incollalo nel file JS di override.

per esempio

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

Quindi includi il tuo file di sostituzione dopo ui-bootstrap e otterrai lo stesso risultato.

Versione biforcuta di pkozlowski.opensource 's Plunk http://plnkr.co/edit/iF5xw2YTrQ0IAalAYiAg?p=preview


1
Uso lo stesso schema e sebbene funzioni; Vorrei davvero che ci fosse un modo migliore. Penso che preferirei la configurazione al clobbering.
bodine

7

È possibile utilizzare template-url="/app/.../_something.template.html"per sovrascrivere il modello corrente per quella direttiva.

(Funziona almeno con Accordion Bootstrap.)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.