web-dev-qa-db-fra.com

Comment exécuter la fonction du contrôleur AngularJS au chargement de la page?

Actuellement, j'ai une page Angular.js qui permet de rechercher et d'afficher les résultats. L'utilisateur clique sur un résultat de recherche, puis clique sur le bouton précédent. Je souhaite que les résultats de la recherche soient à nouveau affichés, mais je ne peux pas déterminer comment déclencher l'exécution de la recherche. Voici le détail:

  • Ma page Angular.js est une page de recherche, avec un champ de recherche et un bouton de recherche. L'utilisateur peut taper manuellement une requête et appuyer sur un bouton. Une requête ajax est déclenchée et les résultats sont affichés. Je mets à jour l'URL avec le terme de recherche. Tout cela fonctionne bien.
  • L'utilisateur clique sur un résultat de la recherche et est redirigé vers une autre page - cela fonctionne également.
  • L'utilisateur clique sur le bouton Précédent et retourne à la page de recherche angular. L'URL correcte s'affiche, ainsi que le terme recherché. Tout fonctionne bien.
  • J'ai lié la valeur du champ de recherche au terme de recherche dans l'URL, qui contient donc le terme de recherche attendu. Tout fonctionne bien.

Comment faire pour que la fonction de recherche s'exécute à nouveau sans que l'utilisateur ait à appuyer sur le "bouton de recherche"? Si c’était jquery, j’exécuterais une fonction dans la fonction documentready. Je ne vois pas l'équivalent angular.js.

354
Duke Dougal

D'une part, comme @ Mark-Rajcok a dit que vous pouvez vous en tirer avec une fonction interne privée:

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

Vous pouvez aussi jeter un oeil à la directive ng-init . La mise en œuvre ressemblera beaucoup à:

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

Mais faites attention car la documentation angulaire implique (depuis la v1.2) de ne PAS utiliser ng-init pour cela. Cependant, cela dépend de l'architecture de votre application.

J'ai utilisé ng-init lorsque je voulais transmettre une valeur de back-end à angular app:

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

Essaye ça?

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

Je ne pourrais jamais obtenir que $viewContentLoaded fonctionne pour moi, et ng-init ne devrait en réalité être utilisé que dans un ng-repeat (selon la documentation), et appeler une fonction directement dans un contrôleur peut également causer erreurs si le code repose sur un élément qui n'a pas encore été défini.

C'est ce que je fais et ça marche pour moi:

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

Sauf si vous utilisez ui-router. Alors c'est:

$scope.$on('$stateChangeSuccess', function () {
  // do something
});
59
adam0101
angular.element(document).ready(function () {

    // your code here

});
42
Carlos Trujillo

La solution de Dimitri/Mark ne fonctionnait pas pour moi, mais l'utilisation de la fonction $ timeout semble bien fonctionner pour garantir que votre code ne s'exécutera qu'après le rendu du balisage.

# Your controller, including $timeout

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

$timeout($scope.init)

J'espère que ça aide.

29
guico

Vous pouvez le faire si vous souhaitez que l'objet DOM viewContentLoaded soit modifié, puis que vous fassiez quelque chose. utiliser $ scope. $ on fonctionne aussi mais différemment, surtout lorsque vous avez un mode page sur votre routage.

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

Vous pouvez utiliser l'objet $ window de angular:

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

Une autre alternative:

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

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

4
ANeves

Lorsque vous utilisez $ routeProvider, vous pouvez résoudre sur .state et bootstrap votre service. C'est-à-dire que vous allez charger Controller et View uniquement après avoir résolu votre service:

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

Un service

function ourBootstrapService() {

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

J'ai eu le même problème et seule cette solution a fonctionné pour moi (elle exécute une fonction après le chargement d'un DOM complet). J'utilise ceci pour faire défiler l'ancre après le chargement de la page:

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

                        // Your function that runs after all DOM is loaded

                    });
3
Ginko Balboa

Encore une autre alternative si vous avez un contrôleur spécifique à cette page:

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

Trouvé Dmitry Evseev répondre assez utile.

Cas 1: Utilisation d'angularJs uniquement:
Pour exécuter une méthode au chargement de la page, vous pouvez utiliser ng-init dans la vue et déclarer la méthode init dans le contrôleur. Cela dit, l’utilisation de fonctions plus lourdes n’est pas recommandée, comme indiqué dans le valeur angulaire). Docs sur ng-init :

Cette directive peut être utilisée pour ajouter des quantités inutiles de logique dans vos modèles. Il n'y a que quelques utilisations appropriées de ngInit, comme pour le repliement de propriétés spéciales de ngRepeat, comme indiqué dans la démonstration ci-dessous; et pour l'injection de données via un script côté serveur. Outre ces quelques cas, vous devez utiliser des contrôleurs plutôt que ngInit pour initialiser les valeurs sur une étendue.

HTML:

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

Contrôleur:

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

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

    doSearch($routeParams.searchKeyword);
})

Avertissement: N'utilisez pas ce contrôleur pour une autre vue destinée à une intention différente, car la méthode de recherche y sera également exécutée.

Cas 2: Utilisation de Ionic:
Le code ci-dessus fonctionnera, assurez-vous simplement que le cache de vue est désactivé dans le route.js en tant que:

route.js

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

J'espère que cela t'aides

3
Kailas

Vous pouvez enregistrer les résultats de la recherche dans un service commun pouvant être utilisé de n'importe où et ne s'effaçant pas lorsque vous naviguez vers une autre page. Vous pouvez ensuite définir les résultats de la recherche avec les données enregistrées pour le clic ou le bouton Précédent.

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

Pour votre backbutton

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

appelez les méthodes initiales à l'intérieur de la fonction self initialize.

(function initController() {

    // do your initialize here

})();
0
Uditha Prasad