Como executar a função do controlador AngularJS no carregamento da página?

359

Atualmente, tenho uma página Angular.js que permite pesquisar e exibir resultados. O usuário clica em um resultado da pesquisa e depois no botão Voltar. Quero que os resultados da pesquisa sejam exibidos novamente, mas não consigo descobrir como acionar a pesquisa para executar. Aqui está o detalhe:

  • Minha página Angular.js é uma página de pesquisa, com um campo de pesquisa e um botão de pesquisa. O usuário pode digitar manualmente uma consulta e pressionar um botão e a consulta ajax é acionada e os resultados são exibidos. Eu atualizo o URL com o termo de pesquisa. Isso tudo funciona bem.
  • O usuário clica em um resultado da pesquisa e é levado para uma página diferente - que também funciona bem.
  • O usuário clica no botão Voltar e volta à minha página de pesquisa angular, e o URL correto é exibido, incluindo o termo de pesquisa. Tudo funciona bem.
  • Eu vinculei o valor do campo de pesquisa ao termo de pesquisa no URL, para que ele contenha o termo de pesquisa esperado. Tudo funciona bem.

Como faço para executar a função de pesquisa novamente sem que o usuário precise pressionar o "botão de pesquisa"? Se fosse jquery, eu executaria uma função na função documentready. Não consigo ver o equivalente ao Angular.js.

Duke Dougal
fonte
você está usando $routepProvider? Use-o para conectar-se ao serviço em seu aplicativo que fornece dados para os resultados da pesquisa. Não pense em document.readytermos como no jQuery. Difícil de ajudar muito, sem seing como você Pesquisa Wired-se actualmente
charlietfl

Respostas:

430

Por um lado, como @ Mark-Rajcok disse que você pode simplesmente se dar bem com a função interna privada:

// at the bottom of your controller
var init = function () {
   // check if there is query in url
   // and fire search in case its value is not empty
};
// and fire it after definition
init();

Além disso, você pode dar uma olhada na diretiva ng-init . A implementação será muito parecida com:

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

Mas tome cuidado com isso, pois a documentação angular implica (desde a v1.2) NÃO usar ng-initpara isso. No entanto, depende da arquitetura do seu aplicativo.

Eu usei ng-initquando queria passar um valor do back-end para o aplicativo angular:

<div data-ng-controller="myCtrl" data-ng-init="init('%some_backend_value%')"></div>
Dmitry Evseev
fonte
6
@ Duke, você não pode simplesmente colocar o conteúdo da função init () na parte inferior do seu controlador? Ou seja, por que você precisa usar ng-init e ter uma função init ()? Quando o usuário pressiona o botão Voltar, presumo que você esteja alternando visualizações, portanto, um novo myCtrlcontrolador é criado e executado.
Mark Rajcok
24
Enquanto esta solução funciona, diminuí a votação porque a documentação do ng-init desaconselha isso. Especificamente, "O único uso apropriado de ngInit para aliasing propriedades especiais de ngRepeat, como visto na demonstração abaixo. Além desse caso, você deve usar controladores em vez de ngInit para inicializar valores em um escopo".
Jason Capriotti
11
O controlador é instanciado após o html estar em seu lugar.
Dmitry Evseev
3
E se o controlador for reutilizado em outras páginas, mas você apenas desejar acioná-lo em uma página específica?
Roberto Linares
3
@RobertoLinares Pessoalmente, considero as diretrizes um lugar melhor para funcionalidades reutilizáveis. Você pode ter uma directiva com um parâmetro de inicialização: <div smth on-init="doWhatever()">. Claro que depende de um certo caso de uso.
Dmitry Evseev
135

Tente isso?

$scope.$on('$viewContentLoaded', function() {
    //call it here
});
princípio holográfico
fonte
5
Obrigado pela resposta, mas a resposta de Dmitry foi uma correspondência exata com o que estou procurando. Pesquisas adicionais pareciam recomendar o $ viewContentLoaded
Duke Dougal:
7
Os casos de uso são apenas diferentes. Eu uso o método de Mark o tempo todo também.
princípio holográfico
Para o meu caso de uso, essa foi uma solução perfeita. Precisávamos selecionar automaticamente o texto para incentivar o usuário a copiá-lo. A página pode ser recarregada / revisitada várias vezes; portanto, $ viewContentLoaded foi uma correspondência exata. Obrigado!
Olga Gnatenko
É possível que isso seja executado várias vezes? Estou recebendo um comportamento que parece estar imitando isso ...
MadPhysicist
11
Este não funcionou para mim, mas $ scope. $ Watch funcionou. Qual é a principal diferença?
Burak Tokak
59

Eu nunca consegui $viewContentLoadedtrabalhar para mim e ng-initrealmente só deveria ser usado em um ng-repeat(de acordo com a documentação), e também chamar uma função diretamente em um controlador pode causar erros se o código se basear em um elemento que ainda não foi definido. .

Isto é o que eu faço e funciona para mim:

$scope.$on('$routeChangeSuccess', function () {
  // do something
});

A menos que você esteja usando ui-router. Então é:

$scope.$on('$stateChangeSuccess', function () {
  // do something
});
adam0101
fonte
11
Você é demais, meu amigo.
taco
Exatamente o que eu precisava. Eu estava literalmente procurando isso por dois dias!
hellojebus
3
$scope.$on('$routeChangeSuccess'aciona toda vez que os parâmetros no URL são alterados (via, $locationpor exemplo) e, portanto, você pode usar just $scope.$on('$locationChangeSuccess'. Se você precisar de algum gatilho no carregamento / recarregamento da página, use o $scope.$watch('$viewContentLoaded'que foi sugerido aqui. Ele não dispara durante as alterações dos parâmetros de URL.
Neurotransmitter
usando AngularJS 1.17.2, controlador dentro $ routeChangeSuccess trabalhou incrivelmente ... longa adam0101 ao vivo ...
ArifMustafa
43
angular.element(document).ready(function () {

    // your code here

});
Carlos Trujillo
fonte
4
Deve ser a resposta aceita, este é o caminho mais seguro para fazê-lo
Marwen Trabelsi
Isso é bom se não trabalharmos $scopee, em vez disso, trabalharmos com this.
Akash
Para onde isso precisa ir? Eu o tenho no meu modelo e não está sendo disparado.
Dave
Não seria melhor injetar $ document neste caso? angular.element ($ document) .ready ...
jamie
4
Explicação seria apreciada
Hidayt Rahman 15/03
32

A solução de Dimitri / Mark não funcionou para mim, mas o uso da função $ timeout parece funcionar bem para garantir que seu código seja executado somente após a marcação ser processada.

# Your controller, including $timeout

var $scope.init = function(){
 //your code
}

$timeout($scope.init)

Espero que ajude.

guico
fonte
3
Finalmente. Este é o único que funcionou para mim. Obrigado.
precisa saber é
11
Isso funciona. Também não esqueça de limpar o tempo limite com $ timeout.cancel (timer), onde você tem var timer = $ timeout ($ scope.init, milissegundos); assim que sua inicialização estiver concluída. Além disso, eu não acho que $ scope deveria ter um 'var' def no seu código acima
Emmanuel NK
Essa deve ser a resposta aceita. Foi o único que funcionou para mim (tentei todas as respostas acima). Até funciona se você estiver esperando o carregamento de um iframe.
hello_fr1end
Isso funciona ! ViewcontentLoaded não funcionou para mim
cavaleiro das trevas
28

Você pode fazer isso se quiser assistir o objeto DOM viewContentLoaded mudar e, em seguida, fazer alguma coisa. O uso de $ scope. $ on também funciona, mas de maneira diferente, especialmente quando você tem um modo de página no seu roteamento.

 $scope.$watch('$viewContentLoaded', function(){
    // do something
 });
CodeOverRide
fonte
7
Especificamente, se você usar $ rootScope. $ Watch em vez de $ rootScope. $, Ele não será acionado nas alterações de rota, para que você possa usar uma lógica específica para o carregamento da página inicial.
csahlman
19

Você pode usar o objeto $ window do angular:

$window.onload = function(e) {
  //your magic here
}
mcgraw
fonte
3

Outra alternativa, se você tiver um controlador específico para essa página:

(function(){
    //code to run
}());
Chipe
fonte
3

Ao usar $ routeProvider, você pode resolver .state e inicializar seu serviço. Isto é, você irá carregar o Controller e o View, apenas após resolver o seu Serviço:

rotas ui

 .state('nn', {
        url: "/nn",
        templateUrl: "views/home/n.html",
        controller: 'nnCtrl',
        resolve: {
          initialised: function (ourBootstrapService, $q) {

            var deferred = $q.defer();

            ourBootstrapService.init().then(function(initialised) {
              deferred.resolve(initialised);
            });
            return deferred.promise;
          }
        }
      })

Serviço

function ourBootstrapService() {

 function init(){ 
    // this is what we need
 }
}
Leo Lanese
fonte
3

Dmitry Evseev achou a resposta bastante útil.

Caso 1: Usando angularJs sozinho:
Para executar um método no carregamento da página, você pode usar ng-inito modo de exibição e declarar init no controller, tendo dito que o uso da função mais pesada não é recomendado, conforme os documentos angulares no ng-init :

Esta diretiva pode ser abusada para adicionar quantidades desnecessárias de lógica aos seus modelos. Existem apenas alguns usos apropriados do ngInit, como alias de propriedades especiais do ngRepeat, como visto na demonstração abaixo; e para injetar dados via script do lado do servidor. Além desses poucos casos, você deve usar controladores em vez de ngInit para inicializar valores em um escopo.

HTML:

<div ng-controller="searchController()">
    <!-- renaming view code here, including the search box and the buttons -->
</div>

Controlador:

app.controller('SearchCtrl', function(){

    var doSearch = function(keyword){
        //Search code here
    }

    doSearch($routeParams.searchKeyword);
})

Atenção : Não use este controlador para outra visualização destinada a uma intenção diferente, pois isso também fará com que o método de pesquisa seja executado lá.

Caso 2: Usando o Ionic:
O código acima funcionará, apenas certifique-se de que o cache de exibição esteja desativado da seguinte route.jsmaneira:

route.js

.state('app', {
    url           : '/search',
    cache         : false, //disable caching of the view here
    templateUrl   : 'templates/search.html'   ,
    controller    : 'SearchCtrl'
  })

Espero que isto ajude

Kailas
fonte
11
Este tinha apenas um em cima e estava bem no fundo, feliz por ter descido todo o caminho, o cache: falsefez por mim - obrigado!
Rani Kheir
3

Eu tive o mesmo problema e apenas esta solução funcionou para mim (ela executa uma função depois que um DOM completo foi carregado). Eu uso isso para rolar para ancorar depois que a página foi carregada:

angular.element(window.document.body).ready(function () {

                        // Your function that runs after all DOM is loaded

                    });
Ginko Balboa
fonte
2

Você pode salvar os resultados da pesquisa em um serviço comum que pode ser usado de qualquer lugar e não é limpo quando navegar para outra página e, em seguida, você pode definir os resultados da pesquisa com os dados salvos ao clicar no botão Voltar

function search(searchTerm) {
    // retrieve the data here;
    RetrievedData = CallService();
    CommonFunctionalityService.saveSerachResults(RetrievedData);
} 

Para o seu backbutton

function Backbutton() {
    RetrievedData = CommonFunctionalityService.retrieveResults();
}
Heshan
fonte
0

chamar métodos iniciais dentro da função de auto-inicialização.

(function initController() {

    // do your initialize here

})();
Uditha Prasad
fonte