İçerik yüklendikten sonra çağrılacak AngularJs olayı


163

Sayfa içeriği yüklendikten sonra çağırmak istediğim bir fonksiyon var. $ ViewContentLoaded hakkında okudum ve benim için çalışmıyor. Gibi bir şey arıyorum

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

AngularJs denetleyicisinde yukarıdaki çağrı benim için çalışmıyor.


Yanıtlar:


163

$ ViewContentLoaded belgelerine göre , çalışması gerekiyordu

NgView içeriği her yüklendiğinde gönderilir.

$viewContentLoaded olay yayınlanır, bu olayı almak için aşağıdaki gibi bir ana denetleyiciye ihtiyacınız vardır

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

Gönderen MainCtrletkinliği dinleyebilirsiniz

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

Demoyu Kontrol Edin


59
Bu yaklaşımla ilgili sorun, denetleyicilerin bu noktada tam olarak başlatılmamış olmasıdır.
Ash Blue

12
@Reza Haklı, dom eklendiğinde ancak açısal dom işleme bitmeden önce bu olay tetiklenir. Açısal değişken olarak bir id veya sınıf ekleyerek bunu test edebilir ve jQuery ile $ viewContentLoaded içinde bulmaya çalışabilirsiniz. Bulamayacaksın.
Thomas Kekeisen

1
@Reza evet, Thomas form öğesinin $ viewContentLoaded diyelim ki, $ scope.formName.elementName. $ SetValidity ("validateRule", false) içinde erişemediği haklı; "TypeError: undefined öğesinin 'elementName' özelliği okunamıyor"
Mussammil

2
Aynı şey $ rootScope seviyesinde çağrılabilir. $ Scope. $ On yerine, $ rootScope. $ App.run () bloğunun içinde ve içinde olmalıdır
Vil

4
Bu seçenek ng-repeat, karmaşık döngüler ve koşullara dayalı olarak HTML / İçerik oluşturacak birkaç iç içe yönergeniz olduğunda işe yaramaz . $viewContentLoadedOlay tetiklendikten sonra bile oluşturma bir süre daha devam eder . Tüm öğelerin tamamen oluşturulduğundan emin olun ve sonra belirli bir kodu yürütün? Herhangi bir geri bildirim?
tarekahf

104

Açısal <1.6.X

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

Açısal> = 1.6.X

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

Bu app.js içine giriyor mu?
zcoon

3
onu controllers.js adresinden dinleyebilirsiniz
hariszaman

2
Ana app.js dosyasında da çalışır.
Loubot

Bu cevap benim için çalışıyor! Belge öğesi sayfasında 'ready () (kullanımdan kaldırıldı, angular.element (belge) .ready (geri arama)) yerine açısal.element (geri arama) kullanın'
Lovera

Bu benim için çalıştı. Kabul edilen cevap yaklaşımı denetleyicinin içinde çalışmaz.
Fabiano

76

sabit - 2015.06.09

Aşağıdaki gibi bir yönerge ve açısal eleman readyyöntemi kullanın :

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>

veya denetleyici- sözdizimi kullananlar için ...

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

Bunun yararı, kullanıcı arayüzünüzle istediğiniz kadar geniş veya ayrıntılı olabilmeniz ve DOM mantığını denetleyicilerinizden kaldırmanızdır. Bunun önerilen Açısal yol olduğunu iddia ediyorum .

Aynı düğümde çalışan başka direktifleriniz olması durumunda, bu direktife öncelik vermeniz gerekebilir.


bu gerçekten iyi bir çözüm gibi görünüyor, ama çalıştıramadım. en tıkanmış elem.ready( $scope.$apply( readyFunc( $scope ))); bunun neden olabileceğini Herhangi fikirler? Belki açısal bir güncelleme oldu? Her neyse - işe yarayabilirse zarif bir yaklaşım.
domoarigato

1
nm, sorunun ne olduğunu görüyorum. Bir yazım hatası attrs.onReadyvardı, şimdi ne olmalı. Diğer konu ben korkak çağırıyor oldu .... ... kahve bellekten JS dönüştürmek için ne olsun.
jusopi

1
Bence bazı durumlarda iyi olabilir, ama buna karşı argümanlarım: Ben sadece bakışta onun kod beklentileri olduğunu düşünüyorum ki DOM görüntülemek için bazı metin değeri dönecekti, ergo dikkatli bir göz gerektirir; Direktif önceliği açısından herhangi bir zamanlamaya izin vermez, kullanmadığınız sürece kontrolör seviyesinde kalırsınız $timeout; Açıkça bir eklenti oluşturuyorsunuz. Sadece dom olmayan mantığı yürütmek için DOM düğümü; Sadece bu yöntem $ kapsam hiyerarşisinde çok fazla yer alıyorsa, çocuk kapsamları miras alacaktır; sadece NG perspektifinde kötü göründüğünü düşünüyorum;
jusopi

5
$timeout(function() {})Etrafında bir ekledikten sonra benim için çalıştı elem.ready(). Aksi takdirde bir $digest already in progresshata atıyordu . Neyse, bir ton teşekkürler! Son bir saattir bununla mücadele ediyorum.
rkrishnan

1
$ Kapsamını kazmak boş görünüyor. Herhangi bir fikir?
MiloTheGreat

66

{{YourFunction()}}HTML öğesinden sonra ekleyerek doğrudan arayabilirsiniz .

İşte bir Plunker Link.


6
Verdiğiniz çözüm hakkında biraz daha açıklama ekleyerek cevabınızı daha ayrıntılı açıklayabilir misiniz?
abarisone

Bu html öğesi yüklendiğinde bir işlevi çağırmak istediğinizi düşünüyorum. Bu işlevi yukarıda belirtildiği gibi çağırın. Benim tahminim şüphe ile ilgili haklıysa, bu aksi takdirde işe yarayacaktır lütfen sorunuzu ayrıntılı olarak açıklayın. :)
mavi

14
Böyle bir işlevi çağırırken. Bir kez çağrıldığından emin olun, aksi takdirde sindirim döngüsü sonsuz çalışır ve bir hata gösterir
Ashan

2
Bu çözümü beğendim, gerçekten çok basit
Kamuran Sönecek

1
Bu harika - tek bir sorun. Bunu kullandığımda işlevimin 5 kez çalıştığı anlaşılıyor. Bir sayaç ekledim, bu yüzden iyi çalışıyor, ancak bunun neden olacağını bilen biri olup olmadığını merak ediyorum ... Biraz garip görünüyor mu?
itchyspacesuit

22

Google grafikleriyle çalışırken bu mantığı uygulamak zorunda kaldım. ne yaptım denetleyicisi tanımı içinde benim html sonunda ben ekledi oldu.

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

ve bu fonksiyonda mantığınızı çağırmanız yeterlidir.

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

Bunu kullanıyordum, ancak sayfanın üst kısmında, init zaten bazı div yüklenmesini gerektiriyordu, bu yüzden ng-init'i sayfanın altına taşıyarak sorunumu düzeltti, güzel ipucu ve mantıklı.
Gurnard

benim sorunum bana yardımcı olan sadece cevap (jquery mobil boş seçim)
kaiser

Dinamik olarak yüklenen kontrollere uyum sağladığı ve uygulanması çok kolay olduğu için bu gerçek cevaptır.
Jason Sebring

bu cevap bana biraz zaman kazandırdı, kullanım durumum için çok zarif ve etkili
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
    };

}] );

Yukarıdaki yöntem benim için çalıştı


3

onload olayının javascript sürümünü açısal js ile çağırabilirsiniz. bu ng-load olayı div, span, body, iframe, img vb. gibi herhangi bir dom öğesine uygulanabilir. Mevcut projenize ng-load ekleme bağlantısı aşağıdadır.

açısal js için ng-load indir

Aşağıda iframe örneği, yüklendikten sonra kontrolörde testCallbackFunction çağrılacaktır

MİSAL

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>

Lütfen OP'nin sorunu nasıl çözebileceğini göstermek için bazı örnek kodlar ekleyin
jro

@jro Ans'ımı güncelledim. Umarım faydalı olacaktır :)
Darshan Jain

2

Halihazırda devam eden bir $ digest hatası alıyorsanız, bu yardımcı olabilir:

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

Sayfa yükleme işleminden sonra çalıştırma, pencere yükleme etkinliğine bir olay dinleyicisi ayarlayarak kısmen tatmin edilmelidir

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

Açısalın içinde module.run(function()...)modül yapısına ve bağımlılıklara tüm erişime sahip olacaksınız.

Şunları yapabilirsiniz broadcastve emitetkinlik iletişim köprüleri için.

Örneğin:

  • modül set onload olayı ve derleme mantığı
  • mantık gerektiğinde kontrolörlere modül yayın olayı
  • denetleyiciler modül yükü işlemlerine dayalı olarak kendi mantıklarını dinler ve yürütürler.

0

Ben kullanıyordum {{myFunction()}}şablonda ama sonra başka bir yolu bulundu burada kullanarak $timeoutKontrolörün içinde. Paylaşacağımı düşündüm, benim için harika çalışıyor.

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();
});

}]);

Burada tüm cevapları denedim ve nedense benim için işe yarayan tek şey $ timeout. Neden olduğundan emin değilim, ancak ng-include ve hizmet başlatma zamanlaması ile ilgili bir şey olabilir.
Drellgor


0

Belirli bir öğenin tamamen yüklenmesini istiyorsanız, o öğede ng-init kullanın.

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

denetleyicide initModalFacultyInfo () işlevi bulunmalıdır.


0

İç içe görünümler varsa - $ viewContentLoaded iç içe görünümlerin her biri için tetiklenir bulundu. Bu geçici çözümü nihai $ viewContentLoaded'i bulmak için oluşturdum. Prerender'ın gerektirdiği gibi $ window.prerenderReady'yi ayarlamak için iyi çalışıyor gibi görünüyor (ana app.js'de .run () yöntemine giriyor):

// 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.");
};
});

Bu kod soruyu cevaplayabilirken, bu kodun soruyu neden ve / veya nasıl cevapladığı konusunda ek bağlam sağlamak uzun vadeli değerini arttırır.
rollstuhlfahrer

0

Benim için çalışan çözüm şudur:

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);
                        }
                    });
                }
            }
        }
    }
}]);

Denetleyici kodu şudur

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

HTML kodu aşağıdaki gibidir

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

-31

setIntervalYüklenen içeriği beklemek için kullanıyorum . Umarım bu sorunu çözmenize yardımcı olabilir.

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
İnsanlar 2016'da hala setIntervalbir çözüm olarak tavsiye ediyor mu?
Zachary Dahan

ama köşeli basit bir api yok ... nasıl .. nasıl yapılır?
Piotr Kula
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.