Как запустить функцию в контроллере angular на готовом документе?
У меня есть функция в моем контроллере angular, я бы хотел, чтобы эта функция была запущена на готовом документе, но я заметил, что 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
}
Кто-нибудь знает, как я могу это сделать?
Ответы
Ответ 1
Мы можем использовать метод 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/
Ответ 2
См. это сообщение Как выполнить функцию контроллера angular при загрузке страницы?
Для быстрого поиска:
// 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
};
Таким образом, вам не нужно ждать, пока документ будет готов.
Ответ 3
Angular автоматически инициализируется при событии DOMContentLoaded
или когда angular.js script оценивается, если в это время document.readyState установлено значение "complete". На данный момент Angular ищет ng-приложение которая указывает ваш корень приложения.
https://docs.angularjs.org/guide/bootstrap
Это означает, что код контроллера будет запущен после готовности DOM.
Таким образом, это просто $scope.init()
.
Ответ 4
Angular имеет несколько временных точек для запуска выполнения функций. Если вы ищете что-то вроде jQuery
$(document).ready();
Вы можете найти этот аналог в angular очень полезным:
$scope.$watch('$viewContentLoaded', function(){
//do something
});
Это полезно, когда вы хотите манипулировать элементами DOM. Он начнет выполнение только после того, как все те элементы будут загружены.
UPD: что сказано выше, когда вы хотите изменить свойства css. Однако иногда это не работает, когда вы хотите измерить свойства элемента, такие как ширина, высота и т.д. В этом случае вы можете попробовать следующее:
$scope.$watch('$viewContentLoaded',
function() {
$timeout(function() {
//do something
},0);
});
Ответ 5
У меня была аналогичная ситуация, когда мне нужно было выполнить функцию контроллера после загрузки представления, а также после того, как какой-то сторонний компонент в представлении был загружен, инициализирован и разместил ссылку на себя в области $scope. То, что в конечном итоге работало для меня, - это настроить часы на это свойство 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();
}
});
Наблюдатель называется пару раз с undefined значениями. Затем, когда сетка создана и имеет ожидаемое свойство, можно инициализировать функцию инициализации. В первый раз, когда наблюдатель вызывается с не-w91 > newValue, oldValue все равно будет undefined.
Ответ 6
Здесь моя попытка внутри внешнего контроллера с помощью coffeescript. Он работает довольно хорошо. Обратите внимание, что settings.screen.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()
Ответ 7
Ответ
$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)
Таким образом, $ document.ready() в большинстве случаев бесполезен, поскольку DOM, построенный в угловом формате, может быть далеко не готов.
Но что еще интереснее, даже после запуска $ viewContentLoaded интересующий элемент все еще не может быть найден.
Только после выполнения $ timeout он был найден. Обратите внимание, что, хотя значение $ timeout было равно 0, до его выполнения прошло около 200 миллисекунд, что указывает на то, что этот поток удерживался довольно долго, предположительно, в то время как в DOM были добавлены угловые шаблоны в основной поток. Общее время от первого выполнения $ document.ready() до последнего выполнения $ timeout составило почти 500 миллисекунд.
В одном необычном случае, когда было установлено значение компонента, а затем значение text() было изменено позднее в $ timeout, значение $ timeout нужно было увеличивать до тех пор, пока оно не заработало (даже если элемент можно было найти во время $ timeout). Что-то асинхронное в стороннем компоненте заставило значение иметь приоритет над текстом, пока не прошло достаточно времени. Другая возможность - $ scope. $ EvalAsync, но не была опробована.
Я все еще ищу одно событие, которое говорит мне, что DOM полностью остановился и им можно манипулировать, чтобы все случаи работали. Пока что необходимо произвольное значение тайм-аута, то есть в лучшем случае это кладжа, которая может не работать в медленном браузере. Я не пробовал варианты JQuery, такие как liveQuery и публикация/подписка, которые могут работать, но, конечно, не являются чисто угловатыми.
Ответ 8
Почему бы не попробовать, с чем angular docs упоминает https://docs.angularjs.org/api/ng/function/angular.element.
angular.element(обратный вызов)
Я использовал это внутри своей функции $onInit() {...}.
var self = this;
angular.element(function () {
var target = document.getElementsByClassName('unitSortingModule');
target[0].addEventListener("touchstart", self.touchHandler, false);
...
});
Это сработало для меня.
Ответ 9
$scope.$on('$ViewData', function(event) {
//Your code.
});
Ответ 10
Если вы получаете что-то вроде getElementById call returns null
, возможно, это связано с тем, что функция работает, но идентификатор не успел загрузить в DOM.
Попробуйте использовать ответ (к началу) с задержкой. Пример:
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
});
});
}]);