Memperluas Angular Directive

114

Saya ingin membuat sedikit modifikasi pada arahan pihak ke-3 (khususnya Angular UI Bootstrap ). Saya hanya ingin menambahkan ruang lingkup panedirektif:

angular.module('ui.bootstrap.tabs', [])
.controller('TabsController', ['$scope', '$element', function($scope, $element) {
  // various methods
}])
.directive('tabs', function() {
  return {
    // etc...
  };
})
.directive('pane', ['$parse', function($parse) {
  return {
    require: '^tabs',
    restrict: 'EA',
    transclude: true,
    scope:{
      heading:'@',
      disabled:'@' // <- ADDED SCOPE PROPERTY HERE
    },
    link: function(scope, element, attrs, tabsCtrl) {
      // link function
    },
    templateUrl: 'template/tabs/pane.html',
    replace: true
  };
}]);

Tetapi saya juga ingin tetap memperbarui Angular-Bootstrap dengan Bower. Segera setelah saya lari bower update, saya akan menimpa perubahan saya.

Jadi bagaimana cara memperluas arahan ini secara terpisah dari komponen bower ini?

Kyle
sumber
2
Cara terbersih adalah menggunakan $provide.decorator(), lihat jawaban saya di bawah.
Eliran Malka

Jawaban:

96

Mungkin cara termudah untuk menyelesaikannya adalah dengan membuat perintah di aplikasi Anda dengan nama yang sama dengan perintah pihak ketiga. Kedua arahan akan berjalan dan Anda dapat menentukan urutan prosesnya menggunakan priorityproperti (prioritas yang lebih tinggi dijalankan terlebih dahulu).

Kedua arahan tersebut akan berbagi ruang lingkup dan Anda dapat mengakses dan mengubah ruang lingkup arahan pihak ketiga melalui linkmetode arahan Anda .

Opsi 2: Anda juga dapat mengakses cakupan direktif pihak ketiga hanya dengan meletakkan direktif Anda sendiri yang diberi nama secara sewenang-wenang pada elemen yang sama dengannya (dengan asumsi tidak ada direktif yang menggunakan cakupan isolate). Semua arahan cakupan non-isolasi pada suatu elemen akan berbagi cakupan.

Bacaan Lebih Lanjut: https://github.com/angular/angular.js/wiki/Dev-Guide%3A-Understanding-Directives

Catatan: Jawaban saya sebelumnya adalah untuk memodifikasi layanan pihak ketiga, bukan arahan.

Dan
sumber
3
terima kasih @ sh0ber, inilah yang saya butuhkan. Dan jawaban Anda sebelumnya membantu saya juga, perihal: layanan pihak ketiga.
Kyle
Hei, jawaban ini sangat bagus, tetapi saya tidak dapat menemukan dokumentasi apa pun tentang properti "prioritas" untuk arahan. Yang saya temukan hanyalah uraian singkat yang mengatakan "Anda dapat menggunakannya", tetapi tidak dapat menemukan contoh sebenarnya.
Ciel
2
@Ciel Info API direktif tampaknya telah dipindahkan ke $compiledokumen di sini
Dan
60

TL; DR - gimme tha demo!


     Big Demo Button     
 


Gunakan $provide's decorator(), baik, menghias direktif pihak ketiga.

Dalam kasus kami, kami dapat memperluas cakupan direktif seperti ini:

app.config(function($provide) {
    $provide.decorator('paneDirective', function($delegate) {
        var directive = $delegate[0];
        angular.extend(directive.scope, {
            disabled:'@'
        });
        return $delegate;
    });
});

Pertama, kami meminta untuk menghias panedirektif dengan meneruskan namanya, digabungkan dengan Directivesebagai argumen pertama, lalu kami mengambilnya dari parameter callback (yang merupakan larik perintah yang cocok dengan nama itu).

Begitu kita mendapatkannya, kita bisa mendapatkan objek scope dan memperluasnya sesuai kebutuhan. Perhatikan bahwa semua ini harus dilakukan di configblok.

Beberapa catatan

  • Disarankan untuk menambahkan arahan dengan nama yang sama, lalu mengatur tingkat prioritasnya. Selain tidak semantik (yang bahkan tidak sepatah kata pun , saya tahu…), ini juga menimbulkan masalah, misalnya bagaimana jika tingkat prioritas arahan pihak ketiga berubah?

  • JeetendraChauhan telah mengklaim (saya belum mengujinya) bahwa solusi ini tidak akan berfungsi di versi 1.13.

Eliran Malka
sumber
1
saya sarankan Anda memberikan jawaban @ sh0ber (buat arahan lain hanya untuk acara pemancar).
Eliran Malka
2
Catatan singkat tentang jawaban ini (yang berfungsi dengan baik), 'Directive' di 'paneDirective' memang memiliki tujuan ;-) Butuh beberapa saat sebelum saya memikirkannya: stackoverflow.com/questions/19409017/… , lihat yang diterima menjawab.
Roy Milder
2
hi @EliranMalka memeriksa plunker saya plnkr.co/edit/0mvQjHYjQCFS6joYJdwK berharap akan bantuan ini seseorang
Jeetendra Chauhan
1
Tautan ke decorator()rusak (diperbarui ke docs.angularjs.org/api/auto/service/$provide#decorator )
Chris Brown
1
@EliranMalka ya, bindToControllerdiperkenalkan di v1.3. Tetapi perhatikan bahwa ini tidak dapat dianggap sebagai solusi alternatif, ini hanya untuk kasus tertentu di mana arahan asli telah diatur dengan bindToControllerproperti. Ide bagus, saya akan memposting ini sebagai jawaban :)
gilad mayani
6

Solusi lain di mana Anda membuat arahan baru yang memperluasnya tanpa mengubah arahan asli

Solusinya mirip dengan solusi dekorator:

Buat direktif baru dan masukkan sebagai ketergantungan arahan yang ingin Anda perpanjang

app.directive('extendedPane', function (paneDirective) {

  // to inject a directive as a service append "Directive" to the directive name
  // you will receive an array of directive configurations that match this 
  // directive (usually only one) ordered by priority

  var configExtension = {
     scope: {
       disabled: '@'
     }
  }

  return angular.merge({}, paneDirective[0], configExtension)
});

Dengan cara ini Anda dapat menggunakan petunjuk asli dan versi diperpanjang di aplikasi yang sama

kidroca
sumber
2
Ini bagus, hanya yang saya butuhkan untuk memperluas arahan lingkup isolate dengan variabel saya sendiri !! Saya menemukan bahwa angular.extend tidak melakukan deep-copy objek, jadi ini menggantikan objek scope paneDirective dengan yang ini. Alternatifnya adalah angular.merge yang akan mempertahankan cakupan asli dari PaneDirective dan menambahkan / menggabungkan variabel yang ditentukan di sini.
mathewguest
1
ya, angular.mergeseharusnya sudah digunakan, saya akan memperbarui contoh
kidroca
1

Berikut adalah solusi lain untuk skenario berbeda dalam memperluas pengikatan ke arahan yang memiliki bindToControllerproperti.

Catatan: ini bukan alternatif untuk solusi lain yang ditawarkan di sini. Ini hanya menyelesaikan kasus tertentu (tidak tercakup dalam jawaban lain) di mana arahan asli dibuat bindToController.

gilad mayani
sumber