191 votes

Comment implémenter history.back() en angular.js

J'ai une directive qui est l'en-tête du site avec un bouton de retour et je veux, en cliquant dessus, revenir à la page précédente. Comment puis-je le faire à la manière d'Angular ?

J'ai essayé :

{{title}}

et voici le fichier js de la directive :

myApp.directive('siteHeader', function () {
    return {
        restrict: 'E',
        templateUrl: 'partials/siteHeader.html',
        scope: {
            title: '@title',
            icons: '@icons'
        }
    };
});

mais rien ne se passe. J'ai regardé dans l'API d'angular.js sur $location mais je n'ai rien trouvé concernant le bouton de retour ou history.back().

1 votes

Vous avez mentionné que cela a fonctionné pour vous. Cela vous emmène-t-il vers des pages différentes dans votre application ou revient-il simplement en arrière dans le navigateur? Pour moi, cela semble simplement revenir en arrière dans le navigateur.

0 votes

Si vous avez configuré AngularJS pour utiliser le mode HTML5, en allant sur une page déjà dans l'historique du navigateur utilisera la version mise en cache et ne la rechargera pas. Le projet sur lequel je travaille utilise un mélange de code ancien et nouveau, et la page précédente change après que les données sont enregistrées avec AngularJS. Ce n'est pas une option de mettre à niveau la première page pour utiliser AngularJS, donc j'ai dû charger une troisième page, non-AngularJS pour rediriger vers la première. Ce n'est pas une solution idéale, mais ça fonctionne.

264voto

asgoth Points 14599

Vous devez utiliser une fonction de lien dans votre directive :

lien: function(scope, element, attrs) {
     element.on('click', function() {
         $window.history.back();
     });
 }

Voir jsFiddle.

0 votes

Mais j'ai 2 boutons dans mon en-tête : un pour la page d'accueil et un pour revenir en arrière. Si je comprends bien votre code, l'élément dans la fonction de lien est l'élément qui a été cliqué. Dans ce cas, history.back s'appliquera également au bouton de la page d'accueil (ce qui n'est pas bon) ?

0 votes

J'ai un peu modifié l'exemple. Maintenant, il y a deux boutons (retour et avance). Il utilise maintenant jQuery, ce qui signifie que scope.$apply() est nécessaire au clic.

8 votes

Ce code est non testable, vous devriez vraiment utiliser l'objet '$window' au lieu de 'window.'

135voto

Andy Joslin Points 23231

Les routes Angular surveillent l'emplacement du navigateur, donc il suffit d'utiliser simplement window.history.back() en cliquant sur quelque chose pour que ça fonctionne.

HTML:

Reculer!

JS:

$scope.doTheBack = function() {
  window.history.back();
};

Je crée habituellement une fonction globale appelée '$back' sur mon contrôleur d'application, que je mets généralement sur la balise body.

angular.module('myApp').controller('AppCtrl', ['$scope', function($scope) {
  $scope.$back = function() { 
    window.history.back();
  };
}]);

Ensuite, n'importe où dans mon application je peux simplement faire Retour

(Si vous voulez que ce soit plus testable, injectez le service $window dans votre contrôleur et utilisez $window.history.back()).

10 votes

Je déconseillerais de mettre quoi que ce soit dans une "fonction globale". Il y a beaucoup de choses qui peuvent arriver à l'état global. Dans ce cas, c'est surtout sa volatilité. Du code provenant d'une tierce partie (ou d'un autre développeur, si vous êtes dans une grande équipe) placé, par exemple, dans une directive ou un service pourrait facilement modifier le $scope.$back pour ses enfants. Ce qui pourrait être difficile à déboguer. Il est définitivement préférable de injecter un service dans chaque composant, et d'exposer la fonctionnalité où elle est nécessaire. L'exemple est seulement "global pour l'application", mais il y a des risques

0 votes

Source: J'ai eu des choses que j'ai coincées dans un $scope d'application "global", me mordre trop de fois pour les compter, et j'ai arrêté d'utiliser cette technique en faveur des services. Qui peuvent encore être piétinés, mais il est beaucoup plus facile de les découvrir.

66voto

Darren Points 751
app.directive('back', ['$window', function($window) {
        return {
            restrict: 'A',
            link: function (scope, elem, attrs) {
                elem.bind('click', function () {
                    $window.history.back();
                });
            }
        };
    }]);

Utilisez comme ceci:

Retour

0 votes

Je suis content que vous ayez montré la dépendance $window - c'est important.

20voto

Уmed Points 3410

Une autre solution agréable et réutilisable est de créer une directive comme ceci:

app.directive( 'backButton', function() {
    return {
        restrict: 'A',
        link: function( scope, element, attrs ) {
            element.on( 'click', function () {
                history.back();
                scope.$apply();
            } );
        }
    };
} );

puis il suffit de l'utiliser comme ceci:

back

1 votes

Semble fonctionner une fois que vous réorganisez les accolades de fermeture et renommez la directive et l'attribut d'élément pour correspondre.

18voto

Rob Points 890

Si cela vous est utile... J'obtenais l'erreur "10 $digest() iterations reached. Aborting!" lorsque j'utilisais $window.history.back(); avec IE9 (fonctionne bien dans les autres navigateurs bien sûr).

J'ai réussi à le faire fonctionner en utilisant :

setTimeout(function() {
  $window.history.back();
},100);

0 votes

D'autres réponses utilisent simplement window. Vous semblez utiliser le service Angular $window. Peut-être est-ce la cause du problème ?

7 votes

J'ai rencontré la même erreur sous IE9 et cela a résolu le problème. Voir github.com/angular/angular.js/issues/1417. Il a raison d'utiliser $window, toutes les autres réponses sont "incorrectes" à ce sujet, voir docs.angularjs.org/api/ng.$window.

0 votes

Avez-vous une idée de pourquoi 100 ms ? C'est assez long, est-ce que cela fonctionne avec moins ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X