Acara AngularJs untuk memanggil setelah konten dimuat


163

Saya memiliki fungsi yang ingin saya panggil setelah konten halaman dimuat. Saya membaca tentang $ viewContentLoaded dan tidak berfungsi untuk saya. Saya mencari sesuatu seperti

document.addEventListener('DOMContentLoaded', function () { 
     //Content goes here 
}, false);

Panggilan di atas tidak bekerja untuk saya di pengontrol AngularJs.


1
Ini berfungsi dengan baik stackoverflow.com/q/14968690/6521116
Kris Roofe

Jawaban:


163

Menurut dokumentasi $ viewContentLoaded , seharusnya berfungsi

Dipancarkan setiap kali konten ngView dimuat ulang.

$viewContentLoaded acara dipancarkan yang berarti untuk menerima acara ini Anda memerlukan pengendali orang tua seperti

<div ng-controller="MainCtrl">
  <div ng-view></div>
</div>

Dari MainCtrlAnda dapat mendengarkan acara tersebut

  $scope.$on('$viewContentLoaded', function(){
    //Here your view content is fully loaded !!
  });

Periksa Demo


59
Masalah dengan pendekatan ini adalah bahwa pengontrol belum sepenuhnya diinisialisasi pada saat ini.
Ash Blue

12
@Reza Dia benar, acara ini dipecat ketika dom ditambahkan tetapi sebelum sudut selesai memproses dom. Anda dapat menguji ini dengan menambahkan id atau kelas sebagai variabel sudut dan mencoba menemukannya di $ viewContentLoaded dengan jQuery. Anda tidak akan menemukannya.
Thomas Kekeisen

1
@Reza ya, Thomas benar elemen form tidak dapat mengakses di dalam $ viewContentLoaded katakanlah, $ scope.formName.elementName. $ SetValidity ("validateRule", false); akan melempar "TypeError: Tidak dapat membaca properti 'elementName' dari undefined"
Mussammil

2
Hal yang sama dapat dipanggil pada level $ rootScope. Alih-alih $ scope. $ On, seharusnya $ rootScope. $ Pada dan di dalam blok app.run ()
Vil

4
Opsi ini tidak akan berfungsi ketika Anda memiliki ng-repeatdan beberapa arahan bersarang yang akan menghasilkan HTML / Konten berdasarkan loop dan kondisi yang kompleks. Rendering berlanjut selama beberapa waktu, bahkan setelah $viewContentLoadedperistiwa dipicu. Bagaimana Anda dapat memastikan bahwa semua elemen telah sepenuhnya diberikan kemudian jalankan kode tertentu? Ada umpan balik?
tarekahf

104

Angular <1,6.X

angular.element(document).ready(function () {
    console.log('page loading completed');
});

Angular> = 1.6.X

angular.element(function () {
    console.log('page loading completed');
});

Apakah ini masuk dalam app.js?
zcoon

3
Anda dapat mendengarkannya di controllers.js
hariszaman

2
Bekerja ok di file app.js utama juga.
Loubot

Jawaban itu berhasil buat saya! Lihat saja pada halaman elemen dokumentasi 'ready () (usang, gunakan angular.element (callback) alih-alih angular.element (document) .ready (callback))'
Lovera

Ini berhasil untuk saya. Pendekatan jawaban yang diterima tidak berfungsi di dalam pengontrol.
Fabiano

76

diperbaiki - 2015.06.09

Gunakan metode arahan dan elemen sudut readyseperti:

js

.directive( 'elemReady', function( $parse ) {
   return {
       restrict: 'A',
       link: function( $scope, elem, attrs ) {    
          elem.ready(function(){
            $scope.$apply(function(){
                var func = $parse(attrs.elemReady);
                func($scope);
            })
          })
       }
    }
})

html

<div elem-ready="someMethod()"></div>

atau bagi mereka yang menggunakan sintaks controller-as ...

<div elem-ready="vm.someMethod()"></div>

Manfaat dari ini adalah Anda bisa seluas atau granular dengan UI yang Anda inginkan dan Anda menghapus logika DOM dari pengontrol Anda. Saya berpendapat ini adalah cara Angular yang direkomendasikan .

Anda mungkin perlu memprioritaskan arahan ini jika Anda memiliki arahan lain yang beroperasi pada node yang sama.


ini sepertinya solusi yang sangat bagus, tapi saya tidak bisa membuatnya bekerja. itu tercekat pada setiap elem.ready( $scope.$apply( readyFunc( $scope ))); ide mengapa itu mungkin terjadi? Mungkin pembaruan ke sudut terjadi? Bagaimanapun - ini adalah pendekatan yang elegan, jika itu bisa berhasil.
domoarigato

1
nm, saya mengerti apa masalahnya. Ada kesalahan ketik pada attrs.onReady, seharusnya seperti sekarang. Masalah lainnya adalah saya menyebutnya funky ... ... apa yang saya dapat untuk mengkonversi kopi dari memori ke JS.
jusopi

1
Saya pikir dalam kasus-kasus tertentu yang mungkin baik-baik saja, tetapi argumen saya menentangnya adalah: Saya pikir harapan kode-nya ketika hanya melirik adalah bahwa akan mengembalikan beberapa nilai teks untuk ditampilkan di DOM, ergo memerlukan perhatian yang cermat; Itu tidak memungkinkan penentuan waktu dalam hal prioritas direktif, Anda terjebak pada tingkat pengontrol kecuali Anda menggunakan $timeout; Anda secara eksplisit membuat addt. Node DOM hanya untuk menjalankan logika non-dom; Ini hanya dapat digunakan kembali jika metode itu berada jauh di hirarki $ scope sehingga lingkup anak mewarisinya; Saya hanya berpikir itu terlihat buruk dalam perspektif NG;
jusopi

5
Bekerja untuk saya setelah menambahkan $timeout(function() {})sekitar elem.ready(). Kalau tidak, itu melempar $digest already in progresskesalahan. Tapi bagaimanapun, terima kasih banyak! Saya telah berjuang dengan ini selama satu jam terakhir.
rkrishnan

1
Menggali $ scope tampaknya kosong. Ada ide?
MiloTheGreat

66

Anda dapat langsung menyebutnya dengan menambahkan {{YourFunction()}}setelah elemen HTML.

Ini dia Plunker Link.


6
Bisakah Anda menjelaskan lebih lanjut jawaban Anda dengan menambahkan sedikit deskripsi tentang solusi yang Anda berikan?
abarisone

Saya pikir Anda ingin memanggil fungsi ketika elemen html dimuat. Jadi panggil fungsi itu seperti yang disebutkan di atas. Jika dugaan saya benar tentang keraguan Anda, maka ini akan berhasil jika tidak, jelaskan pertanyaan Anda. :)
biru

14
Saat memanggil fungsi seperti ini. Pastikan itu dipanggil sekali atau jika tidak siklus cerna akan berjalan tanpa batas dan menunjukkan kesalahan
Ashan

2
Saya suka solusi ini, benar-benar sangat sederhana
Kamuran Sönecek

1
Ini luar biasa - hanya satu masalah. Tampaknya fungsi saya berjalan 5 kali ketika saya menggunakan ini. Saya menambahkan penghitung sehingga berfungsi dengan baik tetapi saya hanya bertanya-tanya apakah ada yang tahu mengapa itu akan terjadi ... Sepertinya agak aneh lho?
itchyspacesuit

22

Saya harus menerapkan logika ini saat menangani dengan grafik Google. Apa yang saya lakukan adalah bahwa pada akhir definisi pengontrol html saya di dalam saya menambahkan.

  <body>
         -- some html here -- 
--and at the end or where ever you want --
          <div ng-init="FunCall()"></div>
    </body>

dan dalam fungsi itu cukup panggil logika Anda.

$scope.FunCall = function () {
        alert("Called");
}

Saya menggunakan ini tetapi di bagian atas halaman, init memerlukan beberapa div untuk dimuat sudah jadi dengan memindahkan ng-init ke bagian bawah halaman memperbaiki masalah saya, tip yang bagus dan masuk akal.
Gurnard

satu-satunya jawaban yang membantu saya dengan masalah saya (pilihan jquery mobile blank)
kaiser

Ini adalah jawaban yang sebenarnya karena menyesuaikan dengan kontrol yang dimuat secara dinamis dan sangat mudah diimplementasikan.
Jason Sebring

jawaban ini menghemat waktu saya, begitu elegan dan efektif untuk kasus penggunaan saya
Sello

4
var myM = angular.module('data-module');

myM.directive('myDirect',['$document', function( $document ){

    function link( scope , element , attrs ){

        element.ready( function(){

        } );

        scope.$on( '$viewContentLoaded' , function(){

            console.log(" ===> Called on View Load ") ;

        } );

    }

    return {
        link: link
    };

}] );

Metode di atas bekerja untuk saya


3

Anda dapat memanggil versi javascript acara onload di sudut js. acara ng-load ini dapat diterapkan ke elemen dom seperti div, span, body, iframe, img dll. berikut ini adalah tautan untuk menambahkan ng-load di proyek Anda yang sudah ada.

unduh ng-load untuk angular js

Berikut ini adalah contoh untuk iframe, setelah dimuat testCallbackFunction akan dipanggil di controller

CONTOH

JS

    // include the `ngLoad` module
    var app = angular.module('myApp', ['ngLoad']);
    app.controller('myCtrl', function($scope) {
        $scope.testCallbackFunction = function() {
          //TODO : Things to do once Element is loaded
        };

    });  

HTML

  <div ng-app='myApp' ng-controller='myCtrl'> 
      <iframe src="test.html" ng-load callback="testCallbackFunction()">  
  </div>

Silakan tambahkan beberapa kode contoh untuk menunjukkan bagaimana OP dapat memecahkan masalah
jro

@ jro Memperbarui ans saya. Semoga ini akan membantu :)
Darshan Jain

2

Jika Anda mendapatkan $ digest sudah dalam kesalahan yang sedang berjalan, ini mungkin membantu:

return {
        restrict: 'A',
        link: function( $scope, elem, attrs ) {
            elem.ready(function(){

                if(!$scope.$$phase) {
                    $scope.$apply(function(){
                        var func = $parse(attrs.elemReady);
                        func($scope);
                    })
                }
                else {

                    var func = $parse(attrs.elemReady);
                    func($scope);
                }

            })
        }
    }

0

Berjalan setelah pemuatan halaman sebagian harus dipenuhi dengan menyetel pendengar acara ke acara pemuatan jendela

window.addEventListener("load",function()...)

Di dalam module.run(function()...)sudut Anda akan memiliki semua akses ke struktur modul dan dependensi.

Anda dapat broadcastdan emitacara untuk jembatan komunikasi.

Sebagai contoh:

  • modul mengatur onload event dan membangun logika
  • acara siaran modul ke pengendali saat logika membutuhkannya
  • pengendali akan mendengarkan dan menjalankan logikanya sendiri berdasarkan pada proses modul yang dimuat.

0

Saya menggunakan {{myFunction()}}dalam template tetapi kemudian menemukan cara lain di sini menggunakan $timeoutdi dalam controller. Kupikir aku akan membaginya, bekerja bagus untukku.

angular.module('myApp').controller('myCtrl', ['$timeout',
function($timeout) {
var self = this;

self.controllerFunction = function () { alert('controller function');}

$timeout(function () {
    var vanillaFunction = function () { alert('vanilla function'); }();
    self.controllerFunction();
});

}]);

Saya mencoba semua jawaban di sini dan untuk beberapa alasan, $ timeout adalah satu-satunya yang bekerja untuk saya. Tidak yakin mengapa, tapi itu mungkin ada hubungannya dengan ng-include dan waktu memulai layanan.
Drellgor

Saya menambahkan plus untuk {{myFunction ()}}
commonpike

0

Jika Anda ingin elemen tertentu dimuat sepenuhnya, Gunakan ng-init pada elemen itu.

misalnya <div class="modal fade" id="modalFacultyInfo" role="dialog" ng-init="initModalFacultyInfo()"> ..</div>

fungsi initModalFacultyInfo () harus ada di controller.


0

Saya menemukan bahwa jika Anda memiliki tampilan bersarang - $ viewContentLoaded akan dipicu untuk setiap tampilan bersarang. Saya telah membuat solusi ini untuk menemukan $ viewContentLoaded akhir. Tampaknya berfungsi dengan baik untuk menyetel $ window.prerenderReady seperti yang disyaratkan oleh Prerender (masuk ke .run () di app.js utama):

// Trigger $window.prerenderReady once page is stable
// Note that since we have nested views - $viewContentLoaded is fired multiple
// times and we need to go around this problem
var viewContentLoads = 0;
var checkReady = function(previousContentLoads) {
  var currentContentLoads = Number(viewContentLoads) + 0; // Create a local copy of the number of loads
  if (previousContentLoads === currentContentLoads) { // Check if we are in a steady state
    $window.prerenderReady = true; // Raise the flag saying we are ready
  } else {
    if ($window.prerenderReady || currentContentLoads > 20) return; // Runaway check
    $timeout(function() {checkReady(currentContentLoads);}, 100); // Wait 100ms and recheck
  }
};
$rootScope.$on('$stateChangeSuccess', function() {
  checkReady(-1); // Changed the state - ready to listen for end of render
});
$rootScope.$on('$viewContentLoaded', function() {
  viewContentLoads ++;
});

0
var myTestApp = angular.module("myTestApp", []); 
myTestApp.controller("myTestController", function($scope, $window) {
$window.onload = function() {
 alert("is called on page load.");
};
});

Sementara kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang mengapa dan / atau bagaimana kode ini menjawab pertanyaan meningkatkan nilai jangka panjangnya.
rollstuhlfahrer

0

Solusi yang bekerja untuk saya adalah sebagai berikut

app.directive('onFinishRender', ['$timeout', '$parse', function ($timeout, $parse) {
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            if (scope.$last === true) {
                $timeout(function () {
                    scope.$emit('ngRepeatFinished');
                    if (!!attr.onFinishRender) {
                        $parse(attr.onFinishRender)(scope);
                    }
                });
            }

            if (!!attr.onStartRender) {
                if (scope.$first === true) {
                    $timeout(function () {
                        scope.$emit('ngRepeatStarted');
                        if (!!attr.onStartRender) {
                            $parse(attr.onStartRender)(scope);
                        }
                    });
                }
            }
        }
    }
}]);

Kode pengontrol adalah sebagai berikut

$scope.crearTooltip = function () {
     $('[data-toggle="popover"]').popover();
}

Kode html adalah sebagai berikut

<tr ng-repeat="item in $data" on-finish-render="crearTooltip()">

-31

Saya biasa setIntervalmenunggu konten dimuat. Saya harap ini dapat membantu Anda untuk menyelesaikan masalah itu.

var $audio = $('#audio');
var src = $audio.attr('src');
var a;
a = window.setInterval(function(){
    src = $audio.attr('src');
    if(src != undefined){
        window.clearInterval(a);
        $('audio').mediaelementplayer({
            audioWidth: '100%'
        });
    }
}, 0);

13
Apakah orang masih merekomendasikan setIntervalsebagai solusi pada tahun 2016 ?
Zachary Dahan

tetapi tidak ada api sederhana di agular ... bagaimana .. bagaimana melakukannya?
Piotr Kula
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.