Come eseguire la funzione del controller AngularJS al caricamento della pagina?


359

Attualmente ho una pagina Angular.js che consente la ricerca e visualizza i risultati. L'utente fa clic su un risultato della ricerca, quindi fa clic sul pulsante Indietro. Voglio che i risultati della ricerca vengano nuovamente visualizzati, ma non riesco a capire come attivare la ricerca. Ecco il dettaglio:

  • La mia pagina Angular.js è una pagina di ricerca, con un campo di ricerca e un pulsante di ricerca. L'utente può digitare manualmente una query e premere un pulsante e la query Ajax viene attivata e i risultati vengono visualizzati. Aggiornamento l'URL con il termine di ricerca. Funziona tutto bene.
  • L'utente fa clic su un risultato della ricerca e viene indirizzato a una pagina diversa, che funziona anche bene.
  • L'utente fa clic sul pulsante Indietro e torna alla mia pagina di ricerca angolare e viene visualizzato l'URL corretto, incluso il termine di ricerca. Tutto funziona bene.
  • Ho associato il valore del campo di ricerca al termine di ricerca nell'URL, quindi contiene il termine di ricerca previsto. Tutto funziona bene.

Come posso eseguire nuovamente la funzione di ricerca senza che l'utente debba premere il "pulsante Cerca"? Se fosse jquery, esegui una funzione nella funzione già documentata. Non riesco a vedere l'equivalente di Angular.js.


stai usando $routepProvider? Usalo per connetterti al servizio nella tua app che fornisce dati per i risultati della ricerca. Non pensare in document.readytermini come con jQuery. Difficile aiutarti molto senza vedere come hai effettuato la ricerca al momento
charlietfl

Risposte:


430

Da un lato, come ha detto @ Mark-Rajcok, puoi semplicemente scappare con la funzione interiore privata:

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

Inoltre puoi dare un'occhiata alla direttiva ng-init . L'implementazione sarà molto simile a:

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

Ma attenzione, poiché la documentazione angolare implica (dal v1.2) di NON utilizzare ng-initper quello. Tuttavia, dipende dall'architettura della tua app.

Ho usato ng-initquando volevo passare un valore dal back-end all'app angolare:

<div data-ng-controller="myCtrl" data-ng-init="init('%some_backend_value%')"></div>

6
@Duke, non puoi semplicemente mettere il contenuto della funzione init () nella parte inferiore del controller? Cioè, perché hai bisogno di usare ng-init e avere una funzione init ()? Quando l'utente preme il pulsante Indietro, suppongo che si stia cambiando vista, quindi myCtrlviene creato ed eseguito un nuovo controller.
Mark Rajcok,

24
Mentre questa soluzione funziona, ho annullato il voto perché la documentazione di ng-init sconsiglia questo. In particolare, "L'unico uso appropriato di ngInit per aliasare le proprietà speciali di ngRepeat, come mostrato nella demo seguente. Oltre a questo caso, è necessario utilizzare i controller anziché ngInit per inizializzare i valori su un ambito."
Jason Capriotti il

1
Il controller viene istanziato dopo che HTML è al suo posto.
Dmitry Evseev,

3
Cosa succede se il controller viene riutilizzato in altre pagine ma si desidera semplicemente attivarlo su una pagina specifica?
Roberto Linares,

3
@RobertoLinares Personalmente trovo che le direttive siano un posto migliore per funzionalità riutilizzabili. Si può avere una direttiva con un parametro init: <div smth on-init="doWhatever()">. Naturalmente dipende da un determinato caso d'uso.
Dmitry Evseev,

135

Prova questo?

$scope.$on('$viewContentLoaded', function() {
    //call it here
});

5
Grazie per la risposta ma la risposta di Dmitry è stata una corrispondenza esatta con quello che sto cercando. Ulteriori ricerche sembrano sconsigliare $ viewContentLoaded
Duke Dougal

7
I casi d'uso sono solo diversi. Uso sempre anche il metodo di Mark.
principio olografico

Per il mio caso d'uso questa è stata una soluzione perfetta. Abbiamo dovuto selezionare automaticamente il testo per incoraggiare l'utente a copiarlo. La pagina può essere ricaricata / rivisitata più volte, quindi $ viewContentLoaded è stata una corrispondenza esatta. Grazie!
Olga Gnatenko,

È possibile che questo venga eseguito più volte? Sto ottenendo un comportamento che sembra imitare quel ...
MadPhysicist

1
Questo non ha funzionato per me ma $ scope. $ Watch ha funzionato. Qual è la differenza principale?
Burak Tokak,

59

Non potrei mai $viewContentLoadedlavorare per me, e ng-initdovrei davvero usarlo solo in un ng-repeat(secondo la documentazione) e anche chiamare una funzione direttamente in un controller può causare errori se il codice si basa su un elemento che non è stato ancora definito .

Questo è quello che faccio e funziona per me:

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

A meno che tu non stia usando ui-router. Quindi è:

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

1
Sei fantastico, amico mio.
taco,

Esattamente quello di cui avevo bisogno. Lo stavo letteralmente cercando da due giorni!
hellojebus,

3
$scope.$on('$routeChangeSuccess'viene attivato ogni volta che i parametri nell'URL vengono modificati (tramite $locationad esempio) e quindi è possibile utilizzare solo $scope.$on('$locationChangeSuccess'. Se hai bisogno di un trigger al caricamento / ricarica della pagina, puoi usare $scope.$watch('$viewContentLoaded'come suggerito qui. Non si attiva durante la modifica dei parametri dell'URL.
Neurotrasmettitore

usando AngularJS 1.17.2, all'interno del controller $ routeChangeSuccess ha funzionato incredibilmente ... lunga vita adam0101 ...
ArifMustafa

43
angular.element(document).ready(function () {

    // your code here

});

4
Deve essere la risposta accettata, questo è il modo più sicuro per farlo
Marwen Trabelsi

Questo va bene se non lavoriamo con $scopee invece lavoriamo con this.
Akash,

Dove deve andare questo? L'ho nel mio modello e non si attiva.
Dave,

Non sarebbe meglio iniettare $ document in questo caso? angular.element ($ document) .ready ...
jamie,

4
La spiegazione sarebbe apprezzata
Hidayt Rahman,

32

La soluzione di Dimitri / Mark non ha funzionato per me, ma l'utilizzo della funzione $ timeout sembra funzionare bene per garantire che il codice venga eseguito solo dopo il rendering del markup.

# Your controller, including $timeout

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

$timeout($scope.init)

Spero che sia d'aiuto.


3
Finalmente. Questo è l'unico che ha funzionato per me. Grazie.
zmirc,

1
Questo funziona Inoltre, non dimenticare di cancellare il timeout con $ timeout.cancel (timer) dove hai var timer = $ timeout ($ scope.init, millisecondi); una volta effettuata l'inizializzazione. Inoltre, non credo che $ scope dovrebbe avere una 'var' def nel tuo codice sopra
Emmanuel NK

Questa dovrebbe essere la risposta accettata. È stato l'unico che ha funzionato per me (ho provato tutte le risposte sopra). Funziona anche se stai aspettando il caricamento di un iframe.
hello_fr1end,

Questo funziona! viewcontentLoaded non ha funzionato per me
cavaliere oscuro

28

Puoi farlo se vuoi guardare l'oggetto DOM viewContentLoaded per cambiare e fare qualcosa. usando $ scope. $ on funziona anche ma in modo diverso soprattutto quando si dispone di una modalità di pagina sul routing.

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

7
In particolare, se si utilizza $ rootScope. $ Watch anziché $ rootScope. $ Su di esso non si attiverà sulle modifiche del percorso, quindi è possibile utilizzare la logica specifica per il caricamento della pagina iniziale.
csahlman,

19

È possibile utilizzare l'oggetto $ window di angular:

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


3

Ancora un'altra alternativa se hai un controller specifico per quella pagina:

(function(){
    //code to run
}());

3

Quando usi $ routeProvider puoi risolvere su .state e avviare il tuo servizio. Questo per dire che caricherai Controller e View, solo dopo aver risolto il tuo servizio:

ui-routes

 .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;
          }
        }
      })

Servizio

function ourBootstrapService() {

 function init(){ 
    // this is what we need
 }
}

3

Ho trovato la risposta di Dmitry Evseev abbastanza utile.

Caso 1: utilizzo di angularJs da solo:
per eseguire un metodo al caricamento della pagina, è possibile utilizzare ng-initnella vista e dichiarare il metodo init nel controller, avendo detto che l'uso di funzioni più pesanti non è raccomandato, come da Documenti angolari su ng-init :

È possibile abusare di questa direttiva per aggiungere quantità inutili di logica nei modelli. Vi sono solo pochi usi appropriati di ngInit, come ad esempio per l'alias delle proprietà speciali di ngRepeat, come mostrato nella demo seguente; e per l'iniezione di dati tramite scripting lato server. Oltre a questi pochi casi, è necessario utilizzare i controller anziché ngInit per inizializzare i valori su un ambito.

HTML:

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

controller:

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

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

    doSearch($routeParams.searchKeyword);
})

Avvertenza: non utilizzare questo controller per un'altra vista intesa per una diversa intenzione in quanto causerà l'esecuzione del metodo di ricerca anche lì.

Caso 2: utilizzo di Ionic:
il codice sopra funzionerà, assicurati solo che la cache della vista sia disabilitata nel modo seguente route.js:

route.js

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

Spero che sia di aiuto


1
Questo aveva solo uno ed era in fondo, felice di essere andato fino in fondo, l' cache: falseho fatto per me - grazie!
Rani Kheir,

3

Ho avuto lo stesso problema e solo questa soluzione ha funzionato per me (esegue una funzione dopo che è stato caricato un DOM completo). Lo uso per scorrere fino all'ancoraggio dopo che la pagina è stata caricata:

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

                        // Your function that runs after all DOM is loaded

                    });

2

È possibile salvare i risultati della ricerca in un servizio comune che può essere utilizzato da qualsiasi luogo e non si cancella quando si accede a un'altra pagina, quindi è possibile impostare i risultati della ricerca con i dati salvati per il clic del pulsante Indietro

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

Per il tuo backbutton

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

0

chiama i metodi iniziali all'interno della funzione di inizializzazione automatica.

(function initController() {

    // do your initialize here

})();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.