Bisakah Anda mengganti templat tertentu di AngularUI Bootstrap?

88

Saya ingin tahu apakah ada cara untuk mengganti template tunggal dan spesifik dari file ui-bootstrap-tpls. Sebagian besar template default sesuai dengan kebutuhan saya, tetapi ada beberapa template khusus yang ingin saya ganti tanpa melalui seluruh proses untuk mengambil semua template default dan menghubungkannya ke versi non-tpls.

Jeremy Privett
sumber
1
Saya juga menemukan diri saya mendekorasi $modallayanan untuk mendapatkan lebih banyak konfigurasi tanpa (semoga) membuat terlalu banyak sakit kepala pemeliharaan. $provide.decorator('$modal'... Dalam kasus saya, saya tidak ingin membuat modalWindowelemen. Pernah. Saya hanya tidak menggunakannya, dan ini adalah yang terbaik yang bisa saya dapatkan. Saya ingin mendengar cara yang lebih baik jika ada yang memilikinya.
bodine

Jawaban:

123

Ya, arahan dari http://angular-ui.github.io/bootstrap sangat dapat disesuaikan dan mudah untuk mengganti salah satu templat (dan masih bergantung pada templat default untuk arahan lain).

Itu cukup untuk memberi makan $templateCache, baik mengumpankannya secara langsung (seperti yang dilakukan dalam ui-bootstrap-tplsfile) atau - mungkin lebih sederhana - menimpa templat menggunakan <script>direktif ( doc ).

Sebuah contoh buat di mana saya mengganti template peringatan untuk pertukaran xuntuk Closeditunjukkan di bawah ini:

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

pkozlowski.opensource
sumber
19
Saya suka jawaban ini. Saya hanya tidak menyukai kenyataan bahwa itu tidak termasuk dalam halaman dokumentasi Angular UI dan membutuhkan waktu yang cukup lama bagi saya untuk mencari cara melakukan sesuatu yang sederhana seperti menunjukkan modal.
Tri Vuong
2
Dokumentasi @BruceBanner dan contoh kerja yang solid adalah dua kelemahan terbesar dari Angular UI. Proyek ini hebat tetapi membutuhkan cinta pengembang yang lembut dan manis.
Robin van Baalen
1
@RobinvanBaalen ini adalah fitur angular-js (bukan angular-ui), itu sudah didokumentasikan di dokumen resmi angular js
vikki
Silakan periksa jawaban @JcT tentang $ give.decorator, karena itulah cara Angular (cara yang baik dalam kasus ini) untuk menimpa template direktif. Dan itu cukup mudah. Hanya menambahkan / menimpa template ke $ templateCache bukanlah praktik terbaik.
John Bernardsson
@John Saya tidak yakin dari mana Anda mendapatkan hal-hal "itu cara Angular (cara yang baik dalam kasus ini)" dan "hanya menambahkan / menimpa template ke $ templateCache sebenarnya bukan praktik terbaik" tetapi sebagai salah satu sudut- ui dan pengelola sudut Saya dapat meyakinkan Anda bahwa tidak ada yang salah dengan mengganti templat. Kecuali jika Anda memiliki masalah khusus untuk dibagikan ...
pkozlowski.opensource
80

Menggunakan $provide.decorator

Menggunakan $provideuntuk menghias arahan menghindari kebutuhan untuk langsung dipusingkan $templateCache.

Alih-alih, buat html template eksternal Anda seperti biasa, dengan nama apa pun yang Anda suka, lalu timpa petunjuk templateUrluntuk menunjuknya.

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

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

(Perhatikan bahwa Anda harus menambahkan akhiran 'Directive' ke nama direktif yang ingin Anda hiasi. Di atas, kami mendekorasi alertdirektif UI Bootstrap , jadi kami menggunakan namanya alertDirective.)

Karena Anda mungkin sering ingin melakukan lebih dari sekadar menimpa templateUrl, ini memberikan titik awal yang baik untuk memperluas direktif lebih lanjut, misalnya dengan menimpa / membungkus tautan atau fungsi kompilasi ( misalnya ).

JcT
sumber
9
Ini adalah solusi yang tepat dan mengikuti praktik terbaik sudut. Anda sebaiknya JANGAN PERNAH menggunakan string untuk membuat HTML, Anda juga tidak boleh menyertakannya secara eksplisit di file index.html tempat Anda memasukkan skrip pihak ketiga. Terima kasih @JcT!
TommyMac
2
Hai, apakah alertDirectiveitu kata kunci? jika ya, untuk apa kata kuncinya Tabs? Saya mencoba melakukan hal serupa pada tab, tetapi saya melihat melalui alert.js, dan saya tidak melihat di mana mereka alertDirectiveada di sana.
codenamezero
4
Angularjs $compileProvidermelampirkan sufiks 'Directive' ke nama direktif Anda saat Anda mendaftarkannya ( $filterProvidermelakukan serupa dengan sufiks 'Filter'); untuk sebagian besar tujuan ini tidak terlihat, tetapi saat mendekorasi Anda harus menambahkan sufiks ini ke petunjuk yang ingin Anda targetkan. Misalnya, tabDirectiveatau tabsetDirective, dll. Tidak didokumentasikan dengan jelas di mana pun yang dapat saya temukan, tetapi berikut ini referensi untuk perilaku serupa $filterProvidersetidaknya: docs.angularjs.org/api/ng/provider/$filterProvider
JcT
2
Terima kasih banyak @JcT, jawaban yang bagus. Ini adalah cara yang benar untuk pergi. Dan, seperti yang Anda katakan, titik awal yang baik untuk "dekorasi" arahan pihak ketiga :)
John Bernardsson
1
@ValeraTumash: Maaf atas jawaban yang terlambat. Ya, saya pikir konfigurasi Anda akan terhalang; namun, dari Angular v1.3 saya yakin Anda dapat memberikan function(element, attributes)ke templateUrl. Anda dapat menggunakan ini untuk beberapa perilaku dinamis (kembalikan fungsi templateUrl asli atau string url Anda sendiri bergantung pada atribut, dll). Namun, ui.bootstrap sekarang juga menggunakan fungsionalitas yang sama ini untuk memungkinkan Anda memberikan template-urlatribut pada direktif, jadi Anda juga dapat menggunakannya jika Anda senang untuk menyediakan jalur templat secara langsung melalui atribut elemen direktif.
JcT
27

Jawaban dari pkozlowski.opensource sangat berguna dan banyak membantu saya! Saya men-tweaknya dalam kondisi saya untuk memiliki satu file yang mendefinisikan semua template sudut saya menimpa dan memuat JS eksternal untuk menjaga ukuran payload tetap rendah.

Untuk melakukan ini, pergi ke bagian bawah file js sumber ui-bootstrap sudut (misalnya ui-bootstrap-tpls-0.6.0.js) dan temukan template yang Anda minati. Salin seluruh blok yang mendefinisikan template dan tempelkan ke file JS pengganti Anda.

misalnya

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

Kemudian masukkan saja file overrides Anda setelah ui-bootstrap dan Anda akan mendapatkan hasil yang sama.

Versi bercabang dari pkozlowski.opensource 's memetik http://plnkr.co/edit/iF5xw2YTrQ0IAalAYiAg?p=preview

Matt Byrne
sumber
1
Saya menggunakan pola yang sama, dan meskipun berhasil; Saya sangat berharap ada cara yang lebih baik. Saya rasa saya lebih suka konfigurasi daripada clobbering.
bodine
7

Anda dapat menggunakan template-url="/app/.../_something.template.html"untuk mengganti template saat ini untuk direktif tersebut.

(Bekerja di Accordion Bootstrap setidaknya.)

merah tua
sumber