最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular $location.state() vs history.pushState behavior - Stack Overflow

programmeradmin1浏览0评论

I am attempting to build a proof of concept single page application that uses the history api to store the state of the view such that when a user navigates using the browser's back and forward buttons, the previous state will be displayed.

This simple example is a series of page links and few values that get displayed, to show the state of the state (no pun intended).

This is all in a functional plnkr

Basic view:

<div ng-app="testApp">
    <div ng-controller="testCtrl">
        <h1>State Data: {{data.displayText}}</h1>
        <h2>Current Page: {{data.currentPage}}</h2>
        <a ng-click="goToPage(page)" ng-repeat="page in pages" class="page">{{page}}</a>
    </div>
</div>

App/Controller:

var testApp = angular.module('testApp', ['ngRoute'])
  .config(function($locationProvider) {
        $locationProvider.html5Mode(true);
  });

testApp.controller('testCtrl', ['$scope', '$location', function ($scope, $location) {

    // Hardcode some pages
    $scope.pages = [1, 2, 3, 4, 5, 6, 7, 8, 9];

   // Set initial data
    $scope.data = {
        currentPage: 1,
        displayText: "This is the initial state"
    };

    // Set initial data in state
    $location.state($scope.data);

    // Watch for location changes so we can apply state accordingly
    $scope.$on('$locationChangeSuccess', function (a, newUrl, oldUrl) {
        $scope.data = $location.state();
    });

    // Move between pages
    $scope.goToPage = function (page) {

        $scope.data.currentPage = page;
        $scope.data.displayText = "This is page " + page;

        $location.search("page", page);
        $location.state($scope.data);

        //history.pushState($scope.data, null, '/ThisPage?page=' + page);
    };
}]);

You'll notice the mented history.pushState() line. Using that line instead of the $location.search() and $location.state() lines above actually works and performs as I'd expect, but I'd like to get this working using the correct angular way.

EDIT: To be clear, I'm not asking IF I should do this the angular way. I am asking what IS the proper angular way to get this working. The two calls to $location in $scope.goToPage() do not work, but the call to history.pushState (the mented line), does work. I'm obviously missing something for how to achieve this with pure angular and that's what I need help with. Cheers!

I am attempting to build a proof of concept single page application that uses the history api to store the state of the view such that when a user navigates using the browser's back and forward buttons, the previous state will be displayed.

This simple example is a series of page links and few values that get displayed, to show the state of the state (no pun intended).

This is all in a functional plnkr

Basic view:

<div ng-app="testApp">
    <div ng-controller="testCtrl">
        <h1>State Data: {{data.displayText}}</h1>
        <h2>Current Page: {{data.currentPage}}</h2>
        <a ng-click="goToPage(page)" ng-repeat="page in pages" class="page">{{page}}</a>
    </div>
</div>

App/Controller:

var testApp = angular.module('testApp', ['ngRoute'])
  .config(function($locationProvider) {
        $locationProvider.html5Mode(true);
  });

testApp.controller('testCtrl', ['$scope', '$location', function ($scope, $location) {

    // Hardcode some pages
    $scope.pages = [1, 2, 3, 4, 5, 6, 7, 8, 9];

   // Set initial data
    $scope.data = {
        currentPage: 1,
        displayText: "This is the initial state"
    };

    // Set initial data in state
    $location.state($scope.data);

    // Watch for location changes so we can apply state accordingly
    $scope.$on('$locationChangeSuccess', function (a, newUrl, oldUrl) {
        $scope.data = $location.state();
    });

    // Move between pages
    $scope.goToPage = function (page) {

        $scope.data.currentPage = page;
        $scope.data.displayText = "This is page " + page;

        $location.search("page", page);
        $location.state($scope.data);

        //history.pushState($scope.data, null, '/ThisPage?page=' + page);
    };
}]);

You'll notice the mented history.pushState() line. Using that line instead of the $location.search() and $location.state() lines above actually works and performs as I'd expect, but I'd like to get this working using the correct angular way.

EDIT: To be clear, I'm not asking IF I should do this the angular way. I am asking what IS the proper angular way to get this working. The two calls to $location in $scope.goToPage() do not work, but the call to history.pushState (the mented line), does work. I'm obviously missing something for how to achieve this with pure angular and that's what I need help with. Cheers!

Share Improve this question edited Jan 8, 2016 at 19:35 ctorx asked Jan 8, 2016 at 0:13 ctorxctorx 6,9518 gold badges40 silver badges53 bronze badges 1
  • Oh you down voter, be constructive and help make this better by leaving a helpful ment. – ctorx Commented Jan 13, 2016 at 18:36
Add a ment  | 

3 Answers 3

Reset to default 0

using $location.search and state instead of history is absolutely fine according to the AngularJS documentation on their Official site.

https://docs.angularjs/api/ng/service/$location

If you are using pure AngularJS it is always remended to go through an Angular way

history.pushState is not Angular code it just a way how you can manipulate browsers history checkout the link for more details

https://developer.mozilla/en-US/docs/Web/API/History_API

So I would always prefer you to use $location.search and $location.state instead of history.pushState

This is a workaround I discovered on my own.

For whatever reason, when trying to set the $location.state() from within the goToPage() method, the state does not get set. Angular will update the url, but the state data will be null.

I found that you can use $location.search() or $location.path() to modify the url, and then subsequently utilize $location.absUrl() to make a call directly to history.pushState().

The reason this is beneficial is that you don't have to mess around with string parsing to get the URL you want. Angular takes care of that, and we just fetch the value to use with pushState().

I have to think there is a way to do this in Angular, but I haven't found it.

$scope.goToPage = function (page) {
   $scope.data.currentPage = page;
   $scope.data.displayText = "This is page " + page;

   $location.search("page", page);
   history.pushState($scope.data, null, $location.absUrl());
};

After every button press, your history state object will be set to NULL. Comment your next line in your code:

// $scope.data = $location.state();

or ment your event out, because in this case is unnecessary

/*
    Watch for location changes so we can apply state accordingly
    $scope.$on('$locationChangeSuccess', function (a, newUrl, oldUrl) {
        $scope.data = $location.state();
    });
*/

I think, after that your code will work like a charm.

发布评论

评论列表(0)

  1. 暂无评论