Cum se execută funcția controlerului AngularJS la încărcarea paginii? (Programare, Angularjs, Onload)

Duke Dougal a intrebat.

În prezent, am o pagină Angular.js care permite căutarea și afișează rezultatele. Utilizatorul face clic pe un rezultat al căutării, apoi face clic pe butonul înapoi. Vreau ca rezultatele căutării să fie afișate din nou, dar nu reușesc să înțeleg cum să declanșez executarea căutării. Iată care sunt detaliile:

  • Pagina mea Angular.js este o pagină de căutare, cu un câmp de căutare și un buton de căutare. Utilizatorul poate tasta manual o interogare și să apese un buton șiși interogarea ajax este declanșată și rezultatele sunt afișate. Actualizez URL-ul cu termenul de căutare. Totul funcționează bine.
  • Utilizatorul face clic pe un rezultat al căutării și este direcționat către o altă pagină – și asta funcționează bine.
  • Utilizatorul face clic pe butonul de revenire și se întoarce la pagina mea de căutare angulară, iar URL-ul corect este afișat, inclusiv termenul de căutare. Totul funcționează bine.
  • Am legat valoarea câmpului de căutare la termenul de căutare din URL, astfel încât acesta să conțină termenul de căutare așteptat. Totul funcționează bine.

Cum pot face ca funcția de căutare să se execute din nou fără ca utilizatorul să fie nevoit să apese „butonul de căutare”? Dacă ar fi vorba de jquery, atunci aș executa o funcție în funcția documentready. Nu văd echivalentul Angular.js.

Comentarii

  • Folosiți $routepProvider? Folosiți-l pentru a vă conecta la serviciul din aplicația dvs. care furnizează date pentru rezultatele căutării. Nu vă gândiți în document.ready termeni ca în cazul jQuery. Este greu să vă ajut foarte mult fără să văd cum ați configurat căutarea în prezent –  > Por charlietfl.
14 răspunsuri
Dmitri Evseev

Pe de o parte, așa cum a spus @Mark-Rajcok, puteți scăpa doar cu funcția interioară privată:

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

De asemenea, puteți arunca o privire la ng-init directivă. Implementarea va fi foarte asemănătoare:

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

Dar aveți grijă de ea ca documentația angular implică (începând cu v1.2) să NU folosiți ng-init pentru asta. Cu toate acestea, imo depinde de arhitectura aplicației dvs.

Eu am folosit ng-init atunci când am vrut să trec o valoare din back-end în aplicația angular:

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

Comentarii

  • @Duke, nu poți să pui conținutul funcției init() în partea de jos a controlerului tău? Adică, de ce trebuie să folosești ng-init și să ai o funcție init()? Atunci când utilizatorul apasă pe butonul de revenire, presupun că schimbi vizualizările, de unde și o nouă funcție myCtrl controler este creat și se execută. –  > Por Mark Rajcok.
  • 25

  • Deși această soluție funcționează, am votat în minus deoarece documentația ng-init recomandă să nu se facă acest lucru. Mai exact, „Singura utilizare adecvată a ngInit pentru aliasarea proprietăților speciale ale ngRepeat, așa cum se vede în demonstrația de mai jos. În afară de acest caz, ar trebui să folosiți controlori mai degrabă decât ngInit pentru a inițializa valorile pe un domeniu de aplicare.” –  > Por Jason Capriotti.
  • Controlerul este instanțiat după ce html este pe locul său. –  > Por Dmitri Evseev.
  • Ce se întâmplă dacă controlerul este reutilizat în alte pagini, dar doriți să îl declanșați doar pe o anumită pagină? –  > Por Roberto Linares.
  • @RobertoLinares Personal, consider că directivele sunt un loc mai bun pentru funcționalitatea reutilizabilă. Puteți avea o directivă cu un parametru init: <div smth on-init="doWhatever()">. Bineînțeles că depinde de un anumit caz de utilizare. –  > Por Dmitry Evseev.
holografic-principiu

Încercați acest lucru?

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

Comentarii

  • Mulțumesc pentru răspuns, dar răspunsul lui Dmitry a fost o potrivire exactă cu ceea ce caut. Cercetările ulterioare păreau să recomande împotriva $viewContentLoaded –  > Por Duke Dougal.
  • Cazurile de utilizare sunt pur și simplu diferite. Și eu folosesc tot timpul metoda lui Mark. –  > Por holographic-principle.
  • Pentru cazul meu de utilizare, aceasta a fost o soluție perfectă. Aveam nevoie să selectăm automat textul pentru a încuraja utilizatorul să îl copieze. Pagina putea fi reîncărcată/revizuită de mai multe ori, astfel încât $viewContentLoaded era o potrivire exactă. Vă mulțumim! –  > Por Olga Gnatenko.
  • Este posibil ca acest lucru să fie executat de mai multe ori? Primesc un comportament care pare să imite acest lucru … – –  > Por MadPhysicist.
  • Acesta nu a funcționat pentru mine, dar $scope.$watch a funcționat. Care este principala diferență? –  > Por Burak Tokak.
adam010101

Nu am putut obține niciodată $viewContentLoaded să lucreze pentru mine, iar ng-init ar trebui să fie folosit doar în cadrul unui ng-repeat (conform documentației) și, de asemenea, apelarea unei funcții direct într-un controler poate cauza erori dacă codul se bazează pe un element care nu a fost încă definit.

Iată ce fac eu și funcționează pentru mine:

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

Cu excepția cazului în care utilizați ui-router. Atunci este:

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

Comentarii

  • Ești minunat, prietene. –  > Por taco.
  • Exact ceea ce aveam nevoie. Am căutat asta timp de două zile! –  > Por hellojebus.
  • $scope.$on('$routeChangeSuccess' pornește de fiecare dată când parametrii din url se schimbă (prin $location de exemplu), și astfel puteți folosi doar $scope.$on('$locationChangeSuccess'. Dacă aveți nevoie de un declanșator la încărcarea/reîncărcarea paginii, puteți utiliza $scope.$watch('$viewContentLoaded' așa cum s-a sugerat aici. Acesta nu se va declanșa în timpul modificării parametrilor url. –  > Por Neurotransmițător.
  • folosind AngularJS 1.17.2, în interiorul controlerului $routeChangeSuccess a funcționat uimitor….trăiască adam0101… –  > Por ArifMustafa.
Carlos Trujillo
angular.element(document).ready(function () {

    // your code here

});

Comentarii

  • Trebuie să fie răspunsul acceptat, acesta este modul mai sigur de a face acest lucru –  > Por Marwen Trabelsi.
  • Acest lucru este bun dacă nu lucrăm cu $scope și, în schimb, lucrăm cu this. –  > Por Aakash.
  • Unde trebuie să meargă asta? Îl am în șablonul meu și nu este de ardere. –  > Por Dave.
  • Nu ar fi cel mai bine să injectați $document în acest caz? angular.element($document).ready… –  > Por jamie.
  • Explicația ar fi apreciată –  > Por Hidayt Rahman.
guico

Soluția lui Dimitri / Mark nu a funcționat pentru mine, dar folosind $timeout pare să funcționeze bine pentru a vă asigura că codul dvs. se execută numai după ce marcajul este redat.

# Your controller, including $timeout

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

$timeout($scope.init)

Sper că vă ajută.

Comentarii

  • În cele din urmă. Aceasta este singura care a funcționat pentru mine. Mulțumesc. –  > Por zmirc.
  • Acest lucru funcționează. De asemenea, nu uitați să ștergeți timeout-ul cu $timeout.cancel(timer), unde aveți var timer = $timeout($scope.init, milisecunde); odată ce inițializarea dvs. este gata. De asemenea, nu cred că $scope ar trebui să aibă un def ‘var’ în codul tău de mai sus –  > Por Emmanuel N K.
  • Acesta ar trebui să fie răspunsul acceptat. A fost singurul care a funcționat pentru mine (am încercat toate răspunsurile de mai sus). Funcționează chiar și dacă așteptați să se încarce un iframe. –  > Por hello_fr1end.
CodeOverRide

Puteți face acest lucru dacă doriți să urmăriți ca obiectul DOM viewContentLoaded să se schimbe și apoi să faceți ceva. folosind $scope.$on funcționează și el, dar în mod diferit, mai ales atunci când aveți un mod de o pagină pe rutare.

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

Comentarii

  • În mod specific, dacă utilizați $rootScope.$watch în loc de $rootScope.$on, nu se va declanșa la schimbările de traseu, astfel încât să puteți utiliza o logică specifică pentru încărcarea inițială a paginii. –  > Por csahlman.
mcgraw

Puteți utiliza obiectul $window de la angular:

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

ANeves crede că SE este rău

O altă alternativă:

var myInit = function () {
    //...
};
angular.element(document).ready(myInit);

(via https://stackoverflow.com/a/30258904/148412)

Chipe

Încă o alternativă dacă ai un controller doar specific acelei pagini:

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

Leo Lanese

Atunci când folosiți $routeProvider puteți să rezolvați pe .state și să faceți bootstrap pentru serviciul dumneavoastră. Adică, veți încărca Controller și View, doar după ce vă rezolvați serviciul:

ui-route

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

Serviciul

function ourBootstrapService() {

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

Kailas

Am găsit răspunsul lui Dmitry Evseev destul de util.

Cazul 1 : Folosind angularJs singur:
Pentru a executa o metodă la încărcarea paginii, puteți utiliza ng-init în vizualizare și să declarați metoda init în controler, având în vedere că utilizarea funcției heavier nu este recomandată, conform angular Docs on ng-init:

Această directivă poate fi folosită în mod abuziv pentru a adăuga cantități inutile de logică în șabloanele dvs. Există doar câteva utilizări adecvate ale ngInit, cum ar fi pentru aliasarea proprietăților speciale ale ngRepeat, așa cum se vede în demo-ul de mai jos; și pentru injectarea de date prin intermediul scripturilor de pe server. În afară de aceste câteva cazuri, ar trebui să folosiți controlori mai degrabă decât ngInit pentru a inițializa valori pe un domeniu de aplicare.

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

Avertizare : Nu folosiți acest controler pentru o altă vizualizare destinată unei alte intenții, deoarece va face ca metoda de căutare să fie executată și acolo.

Cazul 2 : Utilizarea Ionic:
Codul de mai sus va funcționa, doar asigurați-vă că memoria cache a vizualizării este dezactivată în fișierul route.js as:

route.js

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

Sper că acest lucru vă ajută

Comentarii

  • Acest lucru a avut doar unul în sus și a fost la partea de jos, mă bucur că am mers tot drumul în jos, la cache: false a făcut-o pentru mine – mulțumesc! –  > Por Rani Kheir.
Ginko Balboa

Am avut aceeași problemă și numai această soluție a funcționat pentru mine (rulează o funcție după ce a fost încărcat un DOM complet). Folosesc acest lucru pentru scroll la ancoră după ce pagina a fost încărcată:

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

                        // Your function that runs after all DOM is loaded

                    });

Heshan

Puteți salva rezultatele căutării într-un serviciu comun care poate fi folosit de oriunde și nu se șterge la navigarea pe altă pagină, iar apoi puteți seta rezultatele căutării cu datele salvate pentru clic pe butonul de întoarcere

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

Pentru butonul de întoarcere

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

Uditha Prasad

apelați metodele inițiale în interiorul funcției self initialize.

(function initController() {

    // do your initialize here

})();