Saya baru saja mendapatkan arahan saya untuk menarik template untuk menambahkan elemennya seperti ini:
# CoffeeScript
.directive 'dashboardTable', ->
controller: lineItemIndexCtrl
templateUrl: "<%= asset_path('angular/templates/line_items/dashboard_rows.html') %>"
(scope, element, attrs) ->
element.parent('table#line_items').dataTable()
console.log 'Just to make sure this is run'
# HTML
<table id="line_items">
<tbody dashboard-table>
</tbody>
</table>
Saya juga menggunakan Plugin jQuery yang disebut DataTables. Penggunaan umumnya adalah seperti ini: $ ('table # some_id'). DataTable (). Anda dapat mengirimkan data JSON ke panggilan dataTable () untuk menyediakan data tabel ATAU Anda dapat memiliki data pada halaman dan akan melakukan sisanya .. Saya melakukan yang terakhir, memiliki baris sudah di halaman HTML .
Tetapi masalahnya adalah bahwa saya harus memanggil dataTable () pada tabel # line_items SETELAH DOM siap. Arahan saya di atas memanggil metode dataTable () SEBELUM template ditambahkan ke elemen direktif. Apakah ada cara agar saya dapat memanggil fungsi SETELAH append?
Terima kasih untuk bantuannya!
PEMBARUAN 1 setelah jawaban Andy:
Saya ingin memastikan bahwa metode tautan tidak hanya dipanggil SETELAH semuanya ada di laman, jadi saya mengubah arahan untuk sedikit tes:
# CoffeeScript
#angular.module(...)
.directive 'dashboardTable', ->
{
link: (scope,element,attrs) ->
console.log 'Just to make sure this gets run'
element.find('#sayboo').html('boo')
controller: lineItemIndexCtrl
template: "<div id='sayboo'></div>"
}
Dan saya memang melihat "boo" di div # sayboo.
Kemudian saya mencoba panggilan datatable jquery saya
.directive 'dashboardTable', ->
{
link: (scope,element,attrs) ->
console.log 'Just to make sure this gets run'
element.parent('table').dataTable() # NEW LINE
controller: lineItemIndexCtrl
templateUrl: "<%= asset_path('angular/templates/line_items/dashboard_rows.html') %>"
}
Tidak beruntung di sana
Lalu saya mencoba menambahkan batas waktu:
.directive 'dashboardTable', ($timeout) ->
{
link: (scope,element,attrs) ->
console.log 'Just to make sure this gets run'
$timeout -> # NEW LINE
element.parent('table').dataTable()
,5000
controller: lineItemIndexCtrl
templateUrl: "<%= asset_path('angular/templates/line_items/dashboard_rows.html') %>"
}
Dan itu berhasil. Jadi saya bertanya-tanya apa yang salah dalam versi kode non-timer?
Jawaban:
Jika parameter kedua, "delay" tidak disediakan, perilaku default adalah menjalankan fungsi setelah DOM menyelesaikan rendering. Jadi alih-alih setTimeout, gunakan $ timeout:
sumber
$timeout(fn)
akhirnya panggilansetTimeout(fn, 0)
yang memiliki efek mengganggu eksekusi Javascript dan memungkinkan browser untuk merender konten terlebih dahulu, sebelum melanjutkan eksekusi Javascript itu.Saya memiliki masalah yang sama dan saya yakin jawabannya adalah tidak. Lihat komentar Miško dan beberapa diskusi dalam grup .
Angular dapat melacak bahwa semua fungsi yang dipanggil untuk memanipulasi DOM selesai, tetapi karena fungsi-fungsi itu dapat memicu logika async yang masih memperbarui DOM setelah mereka kembali, Angular tidak dapat diharapkan untuk mengetahuinya. Setiap panggilan balik yang diberikan Angular mungkin bekerja kadang-kadang, tetapi tidak akan aman untuk diandalkan.
Kami menyelesaikan ini secara heuristik dengan setTimeout, seperti yang Anda lakukan.
(Harap diingat bahwa tidak semua orang setuju dengan saya - Anda harus membaca komentar di tautan di atas dan melihat pendapat Anda.)
sumber
Anda dapat menggunakan fungsi 'tautan', juga dikenal sebagai postLink, yang berjalan setelah templat dimasukkan.
Berikan ini bacaan jika Anda berencana membuat arahan, ini sangat membantu: http://docs.angularjs.org/guide/directive
sumber
Meskipun jawaban saya tidak terkait dengan datatables itu membahas masalah manipulasi DOM dan misalnya inisialisasi plugin jQuery untuk arahan yang digunakan pada elemen yang kontennya diperbarui secara async.
Alih-alih menerapkan batas waktu, Anda bisa menambahkan arloji yang akan mendengarkan perubahan konten (atau bahkan pemicu eksternal tambahan).
Dalam kasus saya, saya menggunakan solusi ini untuk menginisialisasi plugin jQuery setelah ng-repeat dilakukan yang menciptakan DOM batin saya - dalam kasus lain saya menggunakannya untuk hanya memanipulasi DOM setelah properti lingkup diubah pada controller. Inilah yang saya lakukan ...
HTML:
JS:
Catatan: Daripada hanya casting variabel myContent ke bool pada atribut my-directive-watch, kita bisa membayangkan ekspresi sewenang-wenang di sana.
Catatan: Mengisolasi ruang lingkup seperti pada contoh di atas hanya dapat dilakukan sekali per elemen - mencoba melakukan ini dengan banyak arahan pada elemen yang sama akan menghasilkan $ compile: multidir Error - lihat: https://docs.angularjs.org / error / $ compile / multidir
sumber
Mungkin saya terlambat menjawab pertanyaan ini. Tapi tetap saja seseorang bisa mendapat manfaat dari jawaban saya.
Saya memiliki masalah serupa dan dalam kasus saya, saya tidak dapat mengubah arahan karena, itu adalah perpustakaan dan mengubah kode perpustakaan bukan praktik yang baik. Jadi yang saya lakukan adalah menggunakan variabel untuk menunggu memuat halaman dan menggunakan ng-if di dalam html saya untuk menunggu render elemen tertentu.
Di controller saya:
Dalam html saya (dalam kasus saya komponen html adalah kanvas)
sumber
Saya memiliki masalah yang sama, tetapi menggunakan sudut + DataTable dengan
fnDrawCallback
+ baris pengelompokan + $ disusun arahan bersarang. Saya menempatkan $ timeout padafnDrawCallback
fungsi saya untuk memperbaiki render pagination.Sebelum contoh, berdasarkan sumber row_grouping:
Setelah contoh:
Bahkan penundaan waktu singkat sudah cukup untuk memungkinkan Angular memberikan arahan Angular terkompilasi saya.
sumber
Tidak ada solusi yang berfungsi untuk saya terima dari menggunakan batas waktu. Ini karena saya menggunakan templat yang secara dinamis dibuat selama postLink.
Namun perlu dicatat, ada batas waktu '0' karena batas waktu menambahkan fungsi yang dipanggil ke antrean peramban yang akan terjadi setelah mesin rendering sudut karena ini sudah dalam antrian.
Lihat ini: http://blog.brunoscopelliti.com/run-a-directive-after-the-dom-has-finished-rendering
sumber
Berikut adalah arahan untuk memiliki tindakan yang diprogram setelah render yang dangkal. Maksud saya dangkal itu akan mengevaluasi setelah elemen yang diberikan dan yang tidak akan terkait ketika kontennya diberikan. Jadi jika Anda memerlukan beberapa sub elemen yang melakukan tindakan post render, Anda harus mempertimbangkan untuk menggunakannya di sana:
maka kamu bisa melakukan:
<div after-render></div>
atau dengan ungkapan yang bermanfaat seperti:
<div after-render="$emit='onAfterThisConcreteThingRendered'"></div>
sumber
Saya mendapatkan ini bekerja dengan arahan berikut:
Dan dalam HTML:
kesulitan memotret jika hal di atas tidak berhasil untuk Anda.
1) perhatikan bahwa 'datatableSetup' adalah setara dengan 'datatable-setup'. Angular mengubah format menjadi case unta.
2) pastikan aplikasi didefinisikan sebelum arahan. misalnya definisi dan arahan aplikasi sederhana.
sumber
Mengikuti fakta bahwa urutan beban tidak dapat diantisipasi, solusi sederhana dapat digunakan.
Mari kita lihat hubungan directive-'user of directive '. Biasanya pengguna arahan akan memasok beberapa data ke arahan atau menggunakan beberapa fungsionalitas (fungsi) persediaan arahan. Arahan di sisi lain mengharapkan beberapa variabel akan didefinisikan pada ruang lingkupnya.
Jika kita dapat memastikan bahwa semua pemain telah memenuhi semua persyaratan tindakan mereka sebelum mereka mencoba melakukan tindakan tersebut - semuanya harus baik-baik saja.
Dan sekarang arahannya:
dan sekarang pengguna direktif html
dan di suatu tempat di pengontrol komponen yang menggunakan arahan:
Itu saja. Ada banyak overhead tetapi Anda bisa kehilangan $ timeout. Kami juga mengasumsikan bahwa komponen yang menggunakan arahan adalah instantiated sebelum arahan karena kita bergantung pada variabel kontrol yang ada ketika direktif tersebut dipakai.
sumber