Как реализовать history.back () в angular.js

191

У меня есть директива, которая является заголовком сайта с кнопкой «Назад», и я хочу щелкнуть, чтобы вернуться на предыдущую страницу. Как мне сделать это угловым способом?

Я пытался:

<header class="title">
<a class="back" ng-class="icons"><img src="../media/icons/right_circular.png" ng-click="history.back()" /></a>
<h1>{{title}}</h1>
<a href="/home" class="home" ng-class="icons"><img src="../media/icons/53-house.png" /></a>   
</header>

и это директива JS:

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

но ничего не происходит Я посмотрел в API angular.js о $ location, но не нашел ничего о кнопке back или history.back().

Бабы-DEV
источник
1
Вы упомянули, что это работает для вас. Это перенесет вас на разные страницы вашего приложения или просто вернет браузер? Похоже, это делает браузер обратно ко мне.
Chookoos
Если вы установили AngularJS для использования режима HTML5, при переходе на любую страницу, уже имеющуюся в истории браузера, будет использоваться кэшированная версия, а не ее перезагрузка. Проект, над которым я работаю, использует смесь старого и нового кода, и предыдущая страница изменяется после сохранения данных в AngularJS. Невозможно обновить первую страницу для использования AngularJS, поэтому мне пришлось загрузить третью страницу, отличную от AngularJS, чтобы перенаправить обратно на первую страницу. Не очень хорошее решение, но оно работает.
CJ Деннис

Ответы:

262

Вам нужно использовать функцию ссылки в вашей директиве:

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

Смотрите jsFiddle .

asgoth
источник
Но у меня есть 2 кнопки в заголовке, одна для дома и одна для спины, если я понимаю ваш код, элемент в функции ссылки - это элемент, по которому щелкнули в этом случае history.back будет применяться также для кнопки домой? (Что не хорошо )
Baba-Dev
Я немного изменил пример. Теперь есть две кнопки (назад и вперед). Теперь он использует jQuery, а это означает, что нужно нажать. $ Apply () при нажатии.
asgoth
8
Этот код не тестируется, вы должны действительно использовать объект $ window вместо окна.
Арбитр
Это работает с IE8? Я не верю, что у него есть история
Нил
5
@Neil, Angular гордо не поддерживает IE8. Так что нет.
Рэп
133

Угловые маршруты следят за местоположением браузера, поэтому будет достаточно просто window.history.back()нажать на что-нибудь.

HTML:

<div class="nav-header" ng-click="doTheBack()">Reverse!</div>

JS:

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

Я обычно создаю глобальную функцию с именем $ back на контроллере приложения, которую я обычно помещаю в тег body.

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

Тогда в любом месте моего приложения я могу просто сделать <a ng-click="$back()">Back</a>

(Если вы хотите, чтобы он был более тестируемым, вставьте службу $ window в ваш контроллер и используйте $window.history.back()).

Эндрю Джослин
источник
9
Я бы рекомендовал не помещать что-либо в «глобальную функцию». Есть очень много вещей, которые могут произойти с глобальным состоянием . В этом случае это в основном изменчивость. Код от третьего лица (или другого разработчика, если вы в большой команде), например, директива или служба, может легко изменить $ scope. $ Back для своих детей. Что может быть трудно отладить. Определенно, лучше внедрять сервис в каждый компонент и раскрывать функциональность там, где это необходимо. Пример только «глобален для приложения», но есть риск
Бен Леш,
Источник: у меня были вещи, которые я застрял в «глобальном» приложении. Область $ укусила меня слишком много раз, чтобы сосчитать, и я перестал использовать эту технику в пользу сервисов. Который все еще может быть взорван, но это намного легче разузнать.
Бен Леш
65

В идеале используйте простую директиву, чтобы сохранить контроллеры свободными от избыточного окна $

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

Используйте как это:

<button back>Back</button>
Даррен
источник
Рад, что вы показали зависимость от $ window - это важно.
Крис Смит
20

Другое хорошее и многократно используемое решение - создать директиву, подобную этой :

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

тогда просто используйте это так:

<a href back-button>back</a>
pleerock
источник
1
Кажется, работает, как только вы переупорядочиваете закрывающие фигурки и переименовываете директиву и элемент attr, чтобы они соответствовали друг другу.
Restrsh
18

В случае, если это полезно ... Я нажимал "10 $ digest () достигли итераций. Отмена!" ошибка при использовании $ window.history.back (); с IE9 (работает нормально в других браузерах, конечно).

Я получил его на работу с помощью:

setTimeout(function() {
  $window.history.back();
},100);
Роб Бигрейв
источник
Другие ответы используют простые window. Вы, кажется, используете $windowсервис Angular. Может быть, это коренная причина?
Superjos
7
Я получил ту же ошибку под IE9, и это решило проблему. См. Github.com/angular/angular.js/issues/1417 Он прав насчет использования $ window, все остальные ответы «неправильны» в этом вопросе, см. Docs.angularjs.org/api/ng.$window
tanguy_k
Есть идеи, почему 100 мс? Это довольно задержка, это работает с меньшими затратами?
Кевин
@Kevin 100 мс были просто продолжительностью, которую я считал разумной, а imo не заметной. Действительно, меньшая задержка может работать.
Роб Бигрейв
У меня возникают похожие проблемы в последней версии Chrome при использовании в моем приложении угловой навигации по умолчанию, и задержка тоже не поможет. Помогло только отключение управления навигацией Angular .
Доми
3

Или вы можете просто использовать код:

onClick="javascript:history.go(-1);"

Подобно:

<a class="back" ng-class="icons">
   <img src="../media/icons/right_circular.png" onClick="javascript:history.go(-1);" />
</a>
Арвинд Кушваха
источник
1
на многих уровнях это выглядит неправильно, ср. это сообщение в блоге почти 10 лет назад
Rocco
1

Произошла синтаксическая ошибка. Попробуйте это, и это должно работать:

directives.directive('backButton', function(){
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('click', function () {
                history.back();
                scope.$apply();
            });
        }
    }
});
Рипан Кумар
источник
1

Угловой 4:

/* typescript */
import { Location } from '@angular/common';
// ...

@Component({
  // ...
})
export class MyComponent {

  constructor(private location: Location) { } 

  goBack() {
    this.location.back(); // go back to previous location
  }
}
krmld
источник
0

Для меня моей проблемой было то, что мне нужно было вернуться назад и затем перейти в другое состояние. Поэтому использование $window.history.back()не сработало, потому что по какой-то причине переход произошел до того, как произошло history.back (), поэтому мне пришлось обернуть свой переход в функцию тайм-аута следующим образом.

$window.history.back();
setTimeout(function() {
  $state.transitionTo("tab.jobs"); }, 100);

Это исправило мою проблему.

deb2fast
источник
0

В AngularJS2 я нашел новый способ, может быть, это то же самое, но в этой новой версии:

import {Router, RouteConfig, ROUTER_DIRECTIVES, Location} from 'angular2/router'; 

(...)

constructor(private _router: Router, private _location: Location) {}

onSubmit() {
    (...)
    self._location.back();
}

После выполнения моей функции я вижу, что мое приложение отправляется на предыдущую страницу, используя местоположение angular2 / router.

https://angular.io/docs/ts/latest/api/common/index/Location-class.html

Пол Леклерк
источник
Это работает, вы должны импортировать его из @ angular / common, а не @ angular / router.
сплетение