it-swarm.com.de

Wie kann ich die Funktion in der Winkelsteuerung auf dem Dokument bereit ausführen?

Ich habe eine Funktion in meinem Winkelcontroller. Ich möchte, dass diese Funktion für das Dokument bereit ausgeführt wird. Ich habe jedoch festgestellt, dass der Winkel beim Ausführen des Doms ausgeführt wird.

 function myController($scope)
 {
     $scope.init = function()
     {
        // I'd like to run this on document ready
     }

     $scope.init(); // doesn't work, loads my init before the page has completely loaded
 }

Weiß jemand, wie ich das angehen kann?

244
foreyez

Wir können die angular.element(document).ready()-Methode verwenden, um Callbacks anzuhängen, wenn das Dokument fertig ist. Wir können den Callback einfach so an den Controller anschließen:

angular.module('MyApp', [])

.controller('MyCtrl', [function() {
    angular.element(document).ready(function () {
        document.getElementById('msg').innerHTML = 'Hello';
    });
}]);

http://jsfiddle.net/jgentes/stwyvq38/1/

429
Will

Siehe diesen Beitrag Wie wird die Winkelsteuerungsfunktion beim Laden der Seite ausgeführt?
Für eine schnelle Suche:

// register controller in html
<div data-ng-controller="myCtrl" data-ng-init="init()"></div>

// in controller
$scope.init = function () {
    // check if there is query in url
    // and fire search in case its value is not empty
};

Auf diese Weise müssen Sie nicht warten, bis das Dokument fertig ist. 

28
vinesh

Angular wird bei DOMContentLoaded-Ereignis oder bei Automatisch initialisiert. Das Script "angle.js" wird ausgewertet, wenn zu diesem Zeitpunkt document.readyState ist auf 'complete' gesetzt. An diesem Punkt sucht Angular nach der NG-App Direktive, die Ihr Anwendungsstammverzeichnis bezeichnet.

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

Dies bedeutet, dass der Controller-Code ausgeführt wird, nachdem das DOM bereit ist.

Also ist es nur $scope.init().

22
Will M

Angular hat mehrere Zeitpunkte, um die Ausführung von Funktionen zu starten. Wenn Sie nach so etwas wie jQuery suchen 

$(document).ready();

Sie finden dieses Analog im Winkel sehr nützlich:

$scope.$watch('$viewContentLoaded', function(){
    //do something
});

Dies ist hilfreich, wenn Sie die DOM-Elemente bearbeiten möchten. Es wird erst ausgeführt, wenn alle Elemente geladen sind.

UPD: Was oben gesagt wurde, funktioniert, wenn Sie CSS-Eigenschaften ändern möchten. Manchmal funktioniert es jedoch nicht, wenn Sie die Elementeigenschaften wie Breite, Höhe usw. messen möchten.

$scope.$watch('$viewContentLoaded', 
    function() { 
        $timeout(function() {
            //do something
        },0);    
});
15
Alex Link

Ich hatte eine ähnliche Situation, in der ich eine Controller-Funktion ausführen musste, nachdem die Ansicht geladen wurde und auch nachdem eine bestimmte Komponente eines Drittanbieters in der Ansicht geladen, initialisiert wurde und einen Verweis auf sich selbst auf $ scope gesetzt hatte. Am Ende arbeitete ich für mich daran, eine Überwachung für diese Scope-Eigenschaft einzurichten und meine Funktion erst nach der Initialisierung auszulösen.

// $scope.myGrid property will be created by the grid itself
// The grid will have a loadedRows property once initialized

$scope.$watch('myGrid', function(newValue, oldValue) {
    if (newValue && newValue.loadedRows && !oldValue) {
        initializeAllTheGridThings();
    }
});

Der Beobachter wird mehrmals mit undefinierten Werten aufgerufen. Wenn dann das Raster erstellt wird und die erwartete Eigenschaft hat, kann die Initialisierungsfunktion sicher aufgerufen werden. Wenn der Watcher zum ersten Mal mit einem nicht undefinierten neuen Wert aufgerufen wird, ist oldValue immer noch undefiniert.

2
MikeyM

Die Antwort 

$scope.$watch('$viewContentLoaded', 
    function() { 
        $timeout(function() {
            //do something
        },0);    
});

ist die einzige, die in den meisten getesteten Szenarien funktioniert. In einer Musterseite mit 4 Komponenten, die alle HTML aus einer Vorlage erstellen, wurde die Reihenfolge der Ereignisse festgelegt

$document ready
$onInit
$postLink
(and these 3 were repeated 3 more times in the same order for the other 3 components)
$viewContentLoaded (repeated 3 more times)
$timeout execution (repeated 3 more times)

Daher ist ein $ document.ready () in den meisten Fällen unbrauchbar, da das in Winkel konstruierte DOM möglicherweise noch nicht fertig ist.

Interessanter ist jedoch, dass selbst nach dem Auslösen von $ viewContentLoaded das interessierende Element nicht gefunden werden konnte.

Erst nach dem $ timeout wurde es gefunden. Obwohl $ Timeout einen Wert von 0 hatte, vergingen fast 200 Millisekunden, bevor er ausgeführt wurde. Dies deutet darauf hin, dass dieser Thread eine Zeitlang unterdrückt wurde, vermutlich, während der DOM in einem Haupt-Thread Winkelvorlagen hinzugefügt hatte. Die Gesamtzeit von der ersten $ document.ready () bis zur letzten $ Timeout-Ausführung betrug fast 500 Millisekunden.

In einem außergewöhnlichen Fall, in dem der Wert einer Komponente festgelegt wurde und der Wert text () später im $ timeout geändert wurde, musste der $ timeout-Wert erhöht werden, bis er funktionierte (obwohl das Element während des $ timeout gefunden wurde ). Etwas asynchron in der Drittanbieter-Komponente hat bewirkt, dass ein Wert Vorrang vor dem Text hat, bis eine ausreichende Zeit verstrichen ist. Eine andere Möglichkeit ist $ scope. $ EvalAsync, wurde aber nicht versucht.

Ich bin immer noch auf der Suche nach dem einen Ereignis, das mir mitteilt, dass sich das DOM vollständig beruhigt hat und so manipuliert werden kann, dass alle Fälle funktionieren. Bisher ist ein beliebiger Timeout-Wert erforderlich, was im besten Fall ein Kludge ist, der mit einem langsamen Browser möglicherweise nicht funktioniert. Ich habe JQuery-Optionen wie LiveQuery und Publish/Subscribe nicht ausprobiert, was zwar funktionieren kann, aber nicht unbedingt eckig ist.

1
Wray Smallwood

Hier ist mein Versuch innerhalb eines äußeren Controllers mit Kaffeescript. Es funktioniert ziemlich gut. Bitte beachten Sie, dass es sich bei settings.screen.xs | sm | md | lg um statische Werte handelt, die in einer nicht-verflochtenen Datei definiert sind, die ich in der App mitliege. Die Werte beziehen sich auf die offiziellen Haltepunkte von Bootstrap 3 für die gleichnamigen Medienabfragegrößen:

xs = settings.screen.xs // 480
sm = settings.screen.sm // 768
md = settings.screen.md // 992
lg = settings.screen.lg // 1200

doMediaQuery = () ->

    w = angular.element($window).width()

    $scope.xs = w < sm
    $scope.sm = w >= sm and w < md
    $scope.md = w >= md and w < lg
    $scope.lg = w >= lg
    $scope.media =  if $scope.xs 
                        "xs" 
                    else if $scope.sm
                        "sm"
                    else if $scope.md 
                        "md"
                    else 
                        "lg"

$document.ready () -> doMediaQuery()
angular.element($window).bind 'resize', () -> doMediaQuery()
1
akutz
$scope.$on('$ViewData', function(event) {
//Your code.
});
0
Shreyansh Kumar

Wenn Sie etwas wie getElementById call returns null erhalten, liegt dies wahrscheinlich daran, dass die Funktion ausgeführt wird, die ID jedoch keine Zeit zum Laden in das DOM hatte.

Versuchen Sie, Wills Antwort (nach oben) mit einer Verzögerung zu verwenden. Beispiel:

angular.module('MyApp', [])

.controller('MyCtrl', [function() {
    $scope.sleep = (time) => {
        return new Promise((resolve) => setTimeout(resolve, time));
    };
    angular.element(document).ready(function () {
        $scope.sleep(500).then(() => {        
            //code to run here after the delay
        });
    });
}]);
0
Mr. Green

Warum versuchen Sie nicht, mit welchen Winkeldokumenten https://docs.angularjs.org/api/ng/function/angular.element zu erwähnen. 

angle.element (Rückruf)

Ich habe dies in meiner $ onInit () {...} - Funktion verwendet.

 var self = this;

 angular.element(function () {
        var target = document.getElementsByClassName('unitSortingModule');
        target[0].addEventListener("touchstart", self.touchHandler, false);
        ...
    });

Das hat bei mir funktioniert.

0
Mahib