AngularJS Directive element method binding - TypeError: Tidak dapat menggunakan operator 'in' untuk mencari 'functionName' dalam 1

92

Ini adalah pengontrol template utama:

app.controller('OverviewCtrl', ['$scope', '$location', '$routeParams', 'websiteService', 'helperService', function($scope, $location, $routeParams, websiteService, helperService) {
    ...     
    $scope.editWebsite = function(id) {
        $location.path('/websites/edit/' + id);
    };
}]);

Ini adalah arahannya:

app.directive('wdaWebsitesOverview', function() {
    return {
        restrict: 'E',
        scope: {
            heading: '=',
            websites: '=',
            editWebsite: '&'
        },
        templateUrl: 'views/websites-overview.html'
    }
});

Beginilah cara direktif diterapkan di template utama:

<wda-websites-overview heading="'All websites'" websites="websites" edit-website="editWebsite(id)"></wda-websites-overview>

dan ini adalah metode yang dipanggil dari template direktif (website-overview.html):

<td data-ng-click="editWebsite(website.id)">EDIT</td>

PERTANYAAN: Ketika EDIT diklik, kesalahan ini muncul di konsol:

TypeError: Tidak dapat menggunakan operator 'dalam' untuk mencari 'editWebsite' di 1

Adakah yang tahu apa yang terjadi di sini?

CodeVirtuoso
sumber

Jawaban:

180

Karena Anda mendefinisikan sebuah ekspresi binding ( &), Anda perlu memanggilnya secara eksplisit dengan parameter literal objek yang berisi idjika Anda ingin mengikatnya dalam HTML sebagai edit-website="editWebsite(id)".

Memang, Angular perlu memahami apa ini iddi HTML Anda, dan karena ini bukan bagian dari cakupan Anda, Anda perlu menambahkan apa yang disebut "penduduk setempat" ke panggilan Anda dengan melakukan:

data-ng-click="editWebsite({id: website.id})"

Atau sebagai alternatif:

data-ng-click="onClick(website.id)"

Dengan kode pengontrol / tautan:

$scope.onClick = function(id) {
  // Ad "id" to the locals of "editWebsite" 
  $scope.editWebsite({id: id});
}

AngularJS menyertakan penjelasan tentang ini dalam dokumentasinya; cari contoh yang melibatkan "close({message: 'closing for now'})"URL berikut:

https://docs.angularjs.org/guide/directive

floribon.dll
sumber
7
Terima kasih atas jawaban Anda dan untuk menunjukkan lokasi yang tepat pada dokumentasi, itu sangat membantu!
Bruno Belotti
1
@floribon Saya tahu ini agak lama, tetapi apakah Anda memiliki contoh mengetik skrip panggilan balik?
tcrite
Ini sangat berguna, Terima kasih.
Anurag pareek
masih berguna bagi orang-orang yang mengerjakan proyek lama .. terima kasih
BMWCMW
" Seringkali diinginkan untuk meneruskan data dari lingkup isolate melalui ekspresi ke lingkup induk; ini dapat dilakukan dengan meneruskan peta nama dan nilai variabel lokal ke dalam fungsi pembungkus ekspresi . Misalnya, hideDialogfungsi mengambil pesan untuk ditampilkan saat dialog disembunyikan. Ini ditentukan dalam direktif dengan memanggil close({message: 'closing for now'}). Kemudian variabel lokal messageakan tersedia dalam on-closeekspresi. "[emph mine] Kebenaran lebih aneh daripada fiksi. Saya ingin tahu bagaimana mereka memilih ini sebagai solusi terbaik untuk penangan acara.
ruffin
6

TL; DR; - Anda mengasumsikan bahwa fungsi terikat sedang diteruskan ke komponen anak. Ini salah Nyatanya, AngularJS sedang mengurai template string dan membuat fungsi baru, yang kemudian memanggil fungsi induk.

Fungsi ini perlu menerima objek dengan kunci dan nilai, bukan variabel biasa.

Penjelasan Lebih Panjang

Ini terjadi ketika Anda telah mengikat fungsi menggunakan '&', dan mencoba memanggil fungsi itu dari pengontrol Anda, meneruskan variabel biasa daripada objek yang berisi nama variabel biasa. Kunci objek diperlukan oleh mesin template untuk mengetahui cara meneruskan nilai ke dalam fungsi terikat.

misalnya. Anda telah menelepon boundFunction('cats')daripadaboundFunction({value: 'cats'})

Contoh yang Berhasil

Katakanlah saya membuat komponen seperti ini:

const MyComponent = {
  bindings: {
    onSearch: '&'
  },
  controller: controller
};

Fungsi ini (di induk) terlihat seperti ini:

onSearch(value) {
  // do search
}

Di template induk saya, sekarang saya bisa melakukan ini:

<my-component on-search="onSearch(value)"></my-component>

Pengikatan di sini akan diurai dari string. Anda tidak benar-benar meneruskan fungsi tersebut. AngularJS membuat fungsi untuk Anda yang memanggil fungsi tersebut. Pengikatan yang dibuat dalam template dapat berisi banyak hal selain pemanggilan fungsi.

AngularJS entah bagaimana perlu mencari tahu dari mana asalnya value, dan ia melakukan ini dengan menerima objek dari induknya.

Di pengontrol myComponent, saya perlu melakukan sesuatu seperti:

handleOnSearch(value) {
  if (this.onSearch) {
    this.onSearch({value: value})
  }
}
superluminer
sumber
1
Bola uang mutlak; terima kasih: " Anda telah menelepon boundFunction('cats')daripadaboundFunction({value: 'cats'}) "
ruffin