Как запустить функцию в угловом контроллере на документ готов?


У меня есть функция в моем угловом контроллере, я бы хотел, чтобы эта функция была запущена на готовом документе, но я заметил, что angular запускает ее при создании dom.

 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
 }

кто-нибудь знает, как я могу это сделать?

9 233

9 ответов:

мы можем использовать angular.element(document).ready() метод для присоединения обратных вызовов, когда документ готов. Мы можем просто прикрепить обратный вызов в контроллере следующим образом:

angular.module('MyApp', [])

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

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

этот пост Как выполнить функцию углового контроллера при загрузке страницы?
Для быстрого поиска:

// 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
};

таким образом, вам не придется ждать, пока документ будет готов.

угловой инициализирует автоматически после DOMContentLoaded событие или когда угловатый.сценарий js оценивается, если в это время документ.в зависимости имеет значение "полный". В этот момент угловой ищет ng-приложение директива, которая обозначает корень приложения.

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

это означает, что код контроллера будет работать после того, как DOM будет готов.

таким образом, это просто $scope.init().

угловой имеет несколько моментов времени, чтобы начать выполнение функций. Если вы ищете что-то вроде jQuery

$(document).ready();

вы можете найти этот аналог в angular, чтобы быть очень полезным:

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

Это полезно, когда вы хотите манипулировать элементами DOM. Он начнет выполняться только после загрузки всех элементов te.

UPD: то, что сказано выше, работает, когда вы хотите изменить свойства css. Однако, иногда это не работает, когда вы хотите измерить свойства элемента, такие как ширина, высота и т. д. В этом случае вы можете попробовать следующее:

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

У меня была аналогичная ситуация, когда мне нужно было выполнить функцию контроллера после загрузки представления, а также после того, как определенный сторонний компонент в представлении был загружен, инициализирован и поместил ссылку на себя в $scope. То, что в конечном итоге работало для меня, состояло в том, чтобы настроить часы на этом свойстве области и запустить мою функцию только после ее инициализации.

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

наблюдатель вызывается несколько раз с неопределенными значениями. Затем, когда сетка будет создана и есть свойство, функция инициализации можно смело назвать. Первый раз, когда наблюдатель вызывается с неопределенным newValue, oldValue все равно будет неопределенным.

вот моя попытка внутри внешнего контроллера с помощью CoffeeScript. Это работает довольно хорошо. Обратите внимание, что настройки.экран.xs|sm|md / lg-это статические значения, определенные в неуглифицированном файле, который я включаю в приложение. Эти значения соответствуют официальным точкам останова Bootstrap 3 для одноименных размеров запросов мультимедиа:

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

ответ

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

это единственный, который работает в большинстве сценариев, которые я тестировал. В образце страницы с 4 компонентами, все из которых строят HTML из шаблона, порядок событий был

$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)

Так $документ.ready () бесполезен в большинстве случаев, так как DOM, построенный в angular, может быть далеко не готов.

но еще интереснее, даже после того, как $viewContentLoaded уволен, элемент интереса все равно не мог быть найдено.

Он был найден только после выполнения $ timeout. Обратите внимание, что, хотя значение $timeout было равно 0, до его выполнения прошло почти 200 миллисекунд, что указывает на то, что этот поток был задержан на довольно долгое время, предположительно, в то время как DOM добавлял угловые шаблоны в основной поток. Общее время от первого $ документа.ready () до последнего $timeout выполнение составляло почти 500 миллисекунд.

в одном исключительном случае, когда было установлено значение компонента а затем значение text () было изменено позже в $timeout, значение $timeout должно было быть увеличено до тех пор, пока оно не сработало (хотя элемент можно было найти во время $timeout). Что-то асинхронное в компоненте 3rd заставило значение иметь приоритет над текстом до тех пор, пока не пройдет достаточное время. Другая возможность - $scope.$evalAsync, но не был опробован.

Я все еще ищу это одно событие, которое говорит мне, что DOM полностью успокоился и им можно манипулировать так что все дела работают. До сих пор произвольное значение тайм-аута необходимо, то есть в лучшем случае это kludge, который может не работать на медленном браузере. Я не пробовал варианты JQuery, такие как liveQuery и publish/subscribe, которые могут работать, но, конечно, не являются чистыми угловыми.

почему бы не попробовать с тем, что угловые документы упоминают https://docs.angularjs.org/api/ng/function/angular.element.

угловое.элемент (обратный вызов)

я использовал это внутри моего $onInit () {...} функция.

 var self = this;

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

это сработало для меня.

$scope.$on('$ViewData', function(event) {
//Your code.
});