AngularJS - fungsi lulus ke direktif

160

Saya punya contoh angularJS

<div ng-controller="testCtrl">

<test color1="color1" updateFn="updateFn()"></test>
</div>
 <script>
  angular.module('dr', [])
.controller("testCtrl", function($scope) {
    $scope.color1 = "color";
    $scope.updateFn = function() {
        alert('123');
    }
})
.directive('test', function() {
    return {
        restrict: 'E',
        scope: {color1: '=',
                updateFn: '&'},
        template: "<button ng-click='updateFn()'>Click</button>",
        replace: true,
        link: function(scope, elm, attrs) { 
        }
    }
});

</script>
</body>

</html>

Saya ingin ketika saya mengklik tombol, kotak peringatan akan muncul, tetapi tidak ada yang ditampilkan.

Ada yang bisa bantu saya?

pengguna2707026
sumber

Jawaban:

243

Untuk memanggil fungsi pengontrol dalam lingkup induk dari dalam direktif lingkup isolasi, gunakan dash-separatednama atribut dalam HTML seperti kata OP.

Juga jika Anda ingin mengirim parameter ke fungsi Anda, panggil fungsi dengan mengirimkan objek:

<test color1="color1" update-fn="updateFn(msg)"></test>

JS

var app = angular.module('dr', []);

app.controller("testCtrl", function($scope) {
    $scope.color1 = "color";
    $scope.updateFn = function(msg) {        
        alert(msg);
    }
});

app.directive('test', function() {
    return {
        restrict: 'E',
        scope: {
            color1: '=',
            updateFn: '&'
        },
        // object is passed while making the call
        template: "<button ng-click='updateFn({msg : \"Hello World!\"})'>
            Click</button>",
        replace: true,        
        link: function(scope, elm, attrs) {             
        }
    }
});

Fiddle

Selalu Belajar
sumber
1
Terima kasih Codezilla atas jawaban Anda, dan saya ingin bertanya tentang keadaan ketika saya ingin mengikat fungsi "updateFn" dari ruang lingkup orang tua untuk mengisolasi ruang lingkup dalam "tes" direktif, apakah itu mungkin?
user2707026
2
The replaceatribut telah usang dalam AngularJS: stackoverflow.com/questions/24194972/...
cdmckay
8
untuk beberapa alasan argumen itu tidak jelas untuk saya.
chovy
1
@chovy Saya pikir argumen ini hanya digunakan setelah Anda memanggil metode itu lagi? Penggunaan braket terbuka pertama tampaknya menjadi format yang diinginkan sudut untuk metode yang baru saja dilewati, tapi saya mungkin salah di sana
markyzm
1
Pemetaan objek updateFn({msg: 'my message'});harus digunakan dalam format itu saat melakukan pemanggilan fungsi di dalam linkfungsi direktif .
Brian
159

Mungkin saya kehilangan sesuatu, tetapi meskipun solusi lain memanggil fungsi lingkup induk tidak ada kemampuan untuk melewati argumen dari kode direktif, ini karena update-fnmemanggil updateFn()dengan parameter tetap, misalnya {msg: "Hello World"}. Sedikit perubahan memungkinkan arahan untuk mengeluarkan argumen, yang saya pikir jauh lebih berguna.

<test color1="color1" update-fn="updateFn"></test>

Perhatikan HTML melewati referensi fungsi, yaitu, tanpa ()tanda kurung.

JS

var app = angular.module('dr', []);

app.controller("testCtrl", function($scope) {
    $scope.color1 = "color";
    $scope.updateFn = function(msg) {        
        alert(msg);
    }
});

app.directive('test', function() {
    return {
        restrict: 'E',
        scope: {
            color1: '=',
            updateFn: '&'
        },
        // object is passed while making the call
        template: "<button ng-click='callUpdate()'>
            Click</button>",
        replace: true,        
        link: function(scope, elm, attrs) {       
          scope.callUpdate = function() {
            scope.updateFn()("Directive Args");
          }
        }
    }
});

Jadi di atas, HTML memanggil callUpdatefungsi lingkup lokal , yang kemudian 'mengambil' updateFn dari lingkup induk dan memanggil fungsi yang dikembalikan dengan parameter yang dapat dihasilkan oleh direktif.

http://jsfiddle.net/mygknek2/

steve
sumber
9
Tidak yakin bagaimana saya bisa mendapatkan suara untuk sesuatu yang berfungsi ?? Anda harus meninggalkan komentar jika akan memilih.
steve
7
Ini berhasil untuk saya. Jika Anda tidak ingin fungsi tambahan cukup tulisng-click="updateFn()('Directive Args')"
Graham Walters
7
Awwww! scope.updateFn () ("Arahan Args"); !! BUKAN scope.updateFn ("Arahan Args"); !!!
Phung D. An
2
Ini memang jawaban yang lebih sempurna !!
vinesh
11
@ Ludwik11 yakin - itu karena scope.updateFn ketika didefinisikan seperti ini adalah fungsi yang mengembalikan fungsi (maka () ()) dan ini karena kita masuk ke dalam lingkup (via update-fn = "updateFn" dalam html) referensi ke fungsi yang kita inginkan dipanggil. Yang pertama () adalah panggilan ke sudut untuk mengembalikan referensi ini, yang kedua () membuat panggilan ke fungsi kita dan di mana kita melewati parameter apa pun. HTH
steve
39

Di tag Html directive 'test' Anda, nama atribut fungsi tidak boleh camelCased, tetapi berbasis dash.

jadi - bukannya:

<test color1="color1" updateFn="updateFn()"></test>

menulis:

<test color1="color1" update-fn="updateFn()"></test>

Ini adalah cara sudut untuk membedakan antara atribut direktif (seperti fungsi update-fn) dan fungsi.

Ofer Segev
sumber
1
terima kasih atas tangkapannya. Saya telah memasukkan itu dalam jawaban saya. Terpilih! :)
AlwaysALearner
10

Bagaimana dengan melewatkan fungsi pengontrol dengan pengikatan dua arah ? Kemudian Anda dapat menggunakannya dalam direktif persis dengan cara yang sama seperti pada template biasa (saya melucuti bagian yang tidak relevan untuk kesederhanaan):

<div ng-controller="testCtrl">

   <!-- pass the function with no arguments -->
   <test color1="color1" update-fn="updateFn"></test>
</div>

<script>
   angular.module('dr', [])
   .controller("testCtrl", function($scope) {
      $scope.updateFn = function(msg) {
         alert(msg);
      }
   })
   .directive('test', function() {
      return {
         scope: {
            updateFn: '=' // '=' bidirectional binding
         },
         template: "<button ng-click='updateFn(1337)'>Click</button>"
      }
   });
</script>

Saya mendarat di pertanyaan ini, karena saya mencoba metode di atas befire, tetapi entah bagaimana itu tidak berhasil. Sekarang ini berfungsi dengan baik.

Márton Tamás
sumber
5

gunakan tanda hubung dan huruf kecil untuk nama atribut (seperti kata jawaban lain):

 <test color1="color1" update-fn="updateFn()"></test>

Dan gunakan "=" bukan "&" dalam ruang lingkup direktif:

 scope: { updateFn: '='}

Kemudian Anda dapat menggunakan updateFn seperti fungsi lainnya:

 <button ng-click='updateFn()'>Click</button>

Ini dia!

Jane
sumber
5
Mengapa Anda menggunakan '=' bukan '&'? ketika saya mencoba ini terus memanggil fungsi saya berulang kali.
user1012500
2
Salah menggunakan '=' untuk ini. Itu untuk objek mengikat dua arah.
Ben Taliadoros
1
Saya pikir, satu-satunya masalah adalah penggunaan tanda kurung di templat pertama. Ini menjalankan fungsi kemudian mengikat hasilnya. Alih-alih, Anda harus memasukkan hanya nama fungsi, seperti ini:update-fn="updateFn"
Márton Tamás
1
Jawaban yang buruk sangat buruk.
towry
4

Saya harus menggunakan "=" mengikat alih-alih "&" karena itu tidak berfungsi. Perilaku aneh.

Gunter Reinitzer
sumber
2
Ini karena Anda kemungkinan besar meneruskan arahan fungsi referensi JS daripada eksekusi. Ketika Anda melewatkan fungsi sebagai argumen ke arahan update-fn="updateFn()"Anda harus menyertakan tanda kurung (dan mungkin params). Melewatkannya sebagai referensi fungsi update-fn="updateFn"tidak akan bekerja dengan &penjilidan
JorgeGRC
0

@JorgeGRC Terima kasih atas jawaban Anda. Namun satu hal, bagian "mungkin" sangat penting. Jika Anda memiliki parameter, Anda harus memasukkannya di template Anda juga dan pastikan untuk menentukan lokal Anda misalnya updateFn({msg: "Directive Args"}.

pengguna2893858
sumber