Como executar a function no controlador angular no documento pronto?

Eu tenho uma function dentro do meu controlador angular, gostaria que essa function fosse executada no documento pronto, mas notei que o ângulo é executado conforme o dom é criado.

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 } 

Alguém sabe como eu posso fazer isso?

Podemos usar o angular.element(document).ready() para append callbacks para quando o documento estiver pronto. Podemos simplesmente append o retorno de chamada no controlador da seguinte forma:

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

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

Veja este post Como executar a function do controlador angular no carregamento da página?
Para pesquisa rápida:

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

Dessa forma, você não precisa esperar até que o documento esteja pronto.

Angular inicializa automaticamente no evento DOMContentLoaded ou quando o script angular.js é avaliado se, nesse momento, document.readyState estiver definido como ‘complete’. Neste ponto, o Angular procura a diretiva ng-app que designa a raiz do seu aplicativo.

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

Isso significa que o código do controlador será executado depois que o DOM estiver pronto.

Portanto, é apenas $scope.init() .

Angular tem vários pontos no tempo para começar a executar funções. Se você procura por algo como jQuery

 $(document).ready(); 

Você pode achar este análogo em angular muito útil:

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

Este é útil quando você quer manipular os elementos DOM. Ele começará a ser executado somente depois que todos os elementos te forem carregados.

UPD: O que foi dito acima funciona quando você deseja alterar as propriedades do css. No entanto, às vezes não funciona quando você deseja medir as propriedades do elemento, como largura, altura etc. Nesse caso, convém tentar o seguinte:

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

Eu tive uma situação semelhante em que precisei executar uma function de controlador depois que a view foi carregada e também depois que um componente específico de terceiros dentro da view foi carregado, inicializado e colocado uma referência a si mesmo no $ scope. O que acabou funcionando para mim foi configurar um relógio nessa propriedade de escopo e triggersr minha function somente depois que ela foi inicializada.

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

O observador é chamado algumas vezes com valores indefinidos. Em seguida, quando a grade é criada e tem a propriedade esperada, a function de boot pode ser chamada com segurança. Na primeira vez que o inspetor for chamado com um novoValor não indefinido, oldValue ainda será indefinido.

Aqui está minha tentativa dentro de um controlador externo usando o coffeescript. Isso funciona muito bem. Observe que settings.screen.xs | sm | md | lg são valores estáticos definidos em um arquivo não-uglificado que incluo no aplicativo. Os valores são pelos pontos de interrupção oficiais do Bootstrap 3 para os tamanhos de consulta de mídia de mesmo nome:

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

A resposta

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

é o único que funciona na maioria dos cenários que testei. Em uma página de amostra com 4 componentes, todos construindo HTML a partir de um modelo, a ordem dos events era

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

Portanto, um $ document.ready () é inútil na maioria dos casos, já que o DOM que está sendo construído em ângulo pode estar longe de estar pronto.

Mas, mais interessante, mesmo depois de $ viewContentLoaded ser acionado, o elemento de interesse ainda não foi encontrado.

Somente após o $ timeout executado foi encontrado. Observe que, embora o $ timeout tenha sido 0, quase 200 milissegundos decorreram antes da execução, indicando que esse thread foi mantido por algum tempo, presumivelmente enquanto o DOM tinha modelos angulares adicionados em um thread principal. O tempo total desde o primeiro $ document.ready () até a última execução $ timeout foi de quase 500 milissegundos.

Em um caso extraordinário em que o valor de um componente foi definido e depois o valor text () foi alterado mais tarde no $ timeout, o valor $ timeout teve que ser aumentado até funcionar (mesmo que o elemento pudesse ser encontrado durante o tempo limite $ ). Algo asynchronous dentro do componente de terceiros fez com que um valor tivesse precedência sobre o texto até que o tempo suficiente passasse. Outra possibilidade é $ scope. $ EvalAsync, mas não foi tentada.

Eu ainda estou procurando por aquele evento que me diz que o DOM foi completamente estabelecido e pode ser manipulado para que todos os casos funcionem. Até agora, um valor de tempo limite arbitrário é necessário, o que significa que, na melhor das hipóteses, é um kludge que pode não funcionar em um navegador lento. Eu não tentei opções JQuery como liveQuery e publicar / assinar que podem funcionar, mas certamente não são puramente angulares.

Por que não tentar com o que documentos angulares mencionam https://docs.angularjs.org/api/ng/function/angular.element .

angular.element (callback)

Eu usei isso dentro da minha function $ onInit () {…}.

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

Isso funcionou para mim.

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