Apa yang saya coba terapkan pada dasarnya adalah handler "on ng repeat finished rendering". Saya dapat mendeteksi ketika itu dilakukan tetapi saya tidak tahu bagaimana cara memicu suatu fungsi darinya.
Periksa biola: http://jsfiddle.net/paulocoelho/BsMqq/3/
JS
var module = angular.module('testApp', [])
.directive('onFinishRender', function () {
return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
element.ready(function () {
console.log("calling:"+attr.onFinishRender);
// CALL TEST HERE!
});
}
}
}
});
function myC($scope) {
$scope.ta = [1, 2, 3, 4, 5, 6];
function test() {
console.log("test executed");
}
}
HTML
<div ng-app="testApp" ng-controller="myC">
<p ng-repeat="t in ta" on-finish-render="test()">{{t}}</p>
</div>
Jawab : Bekerja biola dari finishingmove: http://jsfiddle.net/paulocoelho/BsMqq/4/
element.ready()
potongan itu? Maksud saya .. apakah ini semacam plugin jQuery yang Anda miliki, atau haruskah dipicu ketika elemen sudah siap?Jawaban:
Perhatikan bahwa saya tidak menggunakan
.ready()
melainkan membungkusnya dalam$timeout
.$timeout
memastikan itu dieksekusi ketika elemen-elemen yang diulang telah BENAR-BENAR selesai rendering (karena$timeout
akan dijalankan pada akhir siklus digest saat ini - dan itu juga akan memanggil secara$apply
internal, tidak sepertisetTimeout
). Jadi setelahng-repeat
selesai, kita gunakan$emit
untuk memancarkan suatu peristiwa ke lingkup luar (saudara dan orang tua lingkup).Dan kemudian di controller Anda, Anda dapat menangkapnya dengan
$on
:Dengan html yang terlihat seperti ini:
sumber
$timeout
(yang pada dasarnyasetTimeout
+ Angular$scope.$apply()
) dengansetInterval
.$timeout
akan mengeksekusi hanya sekali perif
kondisi, dan itu akan menjadi pada awal$digest
siklus berikutnya . Untuk info lebih lanjut tentang batas waktu JavaScript, lihat: ejohn.org/blog/how-javascript-timers-worksetTimeout()
dengan 0 penundaan adalah pertanyaan lain meskipun saya harus mengatakan saya tidak pernah menemukan spesifikasi yang sebenarnya untuk antrian acara browser di mana saja, hanya apa yang tersirat oleh single-threadedness dan keberadaansetTimeout()
.on-finish-render="ngRepeatFinished"
? Saat saya tetapkanon-finish-render="helloworld"
, kerjanya sama.Gunakan $ evalAsync jika Anda ingin callback Anda (yaitu, test ()) dieksekusi setelah DOM dibuat, tetapi sebelum browser merender. Ini akan mencegah flicker - ref .
Biola .
Jika Anda benar-benar ingin menelepon panggilan balik setelah rendering, gunakan $ timeout:
Saya lebih suka $ eval daripada acara. Dengan suatu acara, kita perlu mengetahui nama acara dan menambahkan kode ke controller kita untuk acara itu. Dengan $ eval, ada lebih sedikit coupling antara controller dan directive.
sumber
$last
dilakukan? Tidak dapat menemukannya di dokumen. Apakah sudah dihapus?$last
didefinisikan pada ruang lingkup jika suatung-repeat
elemen aktif.$timeout
.Jawaban yang telah diberikan sejauh ini hanya akan berfungsi saat pertama kali
ng-repeat
diberikan , tetapi jika Anda memiliki dinamikang-repeat
, artinya Anda akan menambahkan / menghapus / memfilter item, dan Anda harus diberi tahu setiap kali bahwang-repeat
diberikan, solusi itu tidak akan bekerja untuk Anda.Jadi, jika Anda perlu diberi tahu SETIAP SAAT bahwa yang di
ng-repeat
-re-render dan bukan hanya pertama kali, saya telah menemukan cara untuk melakukan itu, ini cukup 'retas', tetapi akan berfungsi dengan baik jika Anda tahu apa yang Anda lakukan perbuatan. Gunakan ini$filter
di Andang-repeat
sebelum Anda menggunakan yang lain$filter
:Ini akan
$emit
acara yang disebutngRepeatFinished
setiap kaling-repeat
mendapat diberikan.Bagaimana cara menggunakannya:
The
ngRepeatFinish
kebutuhan Filter untuk diterapkan langsung keArray
atauObject
didefinisikan dalam Anda$scope
, Anda dapat menerapkan filter lain setelah.Bagaimana TIDAK menggunakannya:
Jangan menerapkan filter lain terlebih dahulu lalu menerapkan
ngRepeatFinish
filter.Kapan saya harus menggunakan ini?
Jika Anda ingin menerapkan gaya css tertentu ke DOM setelah daftar selesai render, karena Anda harus memperhitungkan dimensi baru elemen DOM yang telah dirender ulang oleh
ng-repeat
. (BTW: operasi semacam itu harus dilakukan di dalam arahan)Apa yang TIDAK HARUS DILAKUKAN dalam fungsi yang menangani
ngRepeatFinished
acara:Jangan melakukan
$scope.$apply
dalam fungsi itu atau Anda akan menempatkan Angular dalam loop tanpa akhir yang tidak dapat dideteksi oleh Angular.Jangan menggunakannya untuk membuat perubahan di
$scope
properti, karena perubahan itu tidak akan tercermin dalam tampilan Anda sampai$digest
loop berikutnya , dan karena Anda tidak dapat melakukan itu$scope.$apply
mereka tidak akan ada gunanya."Tapi filter tidak dimaksudkan untuk digunakan seperti itu !!"
Tidak, ini bukan hack, jika Anda tidak suka, jangan menggunakannya. Jika Anda tahu cara yang lebih baik untuk mencapai hal yang sama, mohon beri tahu saya.
Meringkas
sumber
$last
elemen juga diubah,ngRepeatFinish
arahan sederhana dengan memeriksa$last
sekarang akan berfungsi. Segera setelah ngRepeatFinish dipanggil, saya menghapus item dummy. (Saya juga menyembunyikannya dengan CSS agar tidak muncul sebentar)Mark Rajcok
bekerja dengan sempurna setiap pengulangan ulang dari ng-repeat (misalnya karena perubahan model). Jadi solusi hacky ini tidak diperlukan.Jika Anda perlu memanggil fungsi yang berbeda untuk ng-pengulangan yang berbeda pada pengontrol yang sama Anda dapat mencoba sesuatu seperti ini:
Arahan:
Di controller Anda, tangkap acara dengan $ pada:
Dalam template Anda dengan beberapa ng-repeat
sumber
Solusi lain akan bekerja dengan baik pada pemuatan halaman awal, tetapi memanggil $ timeout dari controller adalah satu-satunya cara untuk memastikan bahwa fungsi Anda dipanggil ketika model berubah. Berikut adalah biola yang berfungsi menggunakan $ timeout. Sebagai contoh Anda akan menjadi:
ngRepeat hanya akan mengevaluasi arahan ketika konten baris baru, jadi jika Anda menghapus item dari daftar Anda, onFinishRender tidak akan diaktifkan. Sebagai contoh, coba masukkan nilai filter dalam memancarkan biola ini .
sumber
ta
di dalam$scope.$watch("ta",...
?Jika Anda tidak menolak untuk menggunakan alat peraga lingkup dolar ganda dan Anda sedang menulis arahan yang kontennya hanya pengulangan, ada solusi yang cukup sederhana (dengan asumsi Anda hanya peduli tentang render awal). Dalam fungsi tautan:
Ini berguna untuk kasus-kasus di mana Anda memiliki arahan yang perlu melakukan manipulasi DOM berdasarkan lebar atau tinggi anggota daftar yang diberikan (yang saya pikir adalah alasan paling mungkin seseorang akan mengajukan pertanyaan ini), tetapi itu tidak generik sebagai solusi lain yang telah diusulkan.
sumber
Solusi untuk masalah ini dengan ngRepeat yang difilter dapat dengan Mutasi peristiwa , tetapi mereka sudah usang (tanpa penggantian segera).
Lalu saya memikirkan satu lagi yang mudah:
Ini mengaitkan ke metode Node.prototype dari elemen induk dengan batas waktu $ satu-tik untuk melihat modifikasi berturut-turut.
Sebagian besar kerjanya benar tetapi saya mendapatkan beberapa kasus di mana altDone akan dipanggil dua kali.
Lagi ... tambahkan arahan ini ke induk dari ngRepeat.
sumber
appendChild
juga (karena saya hanya menggunakaninsertBefore
danremoveChild
) dalam kode di atas.Sangat mudah, ini adalah bagaimana saya melakukannya.
sumber
Silakan lihat biola, http://jsfiddle.net/yNXS2/ . Karena arahan yang Anda buat tidak menciptakan ruang lingkup baru saya melanjutkan jalan.
$scope.test = function(){...
membuat itu terjadi.sumber
Saya sangat terkejut tidak melihat solusi paling sederhana di antara jawaban atas pertanyaan ini. Apa yang ingin Anda lakukan adalah menambahkan
ngInit
arahan pada elemen berulang Anda (elemen denganngRepeat
arahan) memeriksa$last
(variabel khusus yang diatur dalam lingkupngRepeat
yang menunjukkan bahwa elemen yang diulang adalah yang terakhir dalam daftar). Jika$last
benar, kami sedang merender elemen terakhir dan kami dapat memanggil fungsi yang kita inginkan.Kode lengkap untuk markup HTML Anda adalah:
Anda tidak memerlukan kode JS tambahan di aplikasi Anda selain fungsi lingkup yang ingin Anda panggil (dalam hal ini,
test
) karenangInit
disediakan oleh Angular.js. Pastikan Anda memilikitest
fungsi dalam lingkup sehingga dapat diakses dari templat:sumber