GithubHelp home page GithubHelp logo

Back Button Support? about ui-router HOT 18 CLOSED

ajoslin avatar ajoslin commented on August 24, 2024 6
Back Button Support?

from ui-router.

Comments (18)

mwager avatar mwager commented on August 24, 2024 5

What about adding a variable to the "event" parameter of "stateChangeStart/stateChangeSuccess" which tells the developer if the event was triggered programmatically or not?

Something like:

$rootScope.$on('$stateChangeStart', function(event) {
  1. $state.go 'some_where' -> event.isTriggeredProgrammatically === true
  2. back button clicked -> event.isTriggeredProgrammatically === false

from ui-router.

ksperling avatar ksperling commented on August 24, 2024

Yes that would be neat. Maybe transitionTo() should have an 'options' object as a third parameter that can contain flags like 'this is a backwards transition', or properties that e.g. ngAnimate could look at to decide what type of animation to use etc.

from ui-router.

0x-r4bbit avatar 0x-r4bbit commented on August 24, 2024

And what about older browser? Should one then load a polyfill (or something like that) to also get a smooth transition, even if window.onpopstate === undefined?

Or would it be more like graceful degradation and there'll be just no transition? Which browsers does ui-router support anyway?

from ui-router.

ksperling avatar ksperling commented on August 24, 2024

Well, back button support is already working in the sense that going back and fowards through history causes the correct state transition. I haven't looked at how (if) $location uses onpopstate internally, but as I see it this would essentially be a case of passing along a 'direction' hint to $state.transitionTo().

I'd think most work for this would actually have to happen in $location, to be able to determine if a location change is 'forward', 'backward', or unknown direction.

from ui-router.

jeme avatar jeme commented on August 24, 2024

@ajoslin The alternation of sliding left or right in git-hubs file browser doesn't depend on using the back button, it depends on what direction you navigate in the file tree...

If you navigate down the tree it slides left
If you navigate up the tree it slides right

What you experience as different behavior on "back button" is properly because you often navigate down (left slide) but then you uses the back button to step up (right slide)... but if you instead click on the parent in the breadcrumbs, it slides right, if you click the back-button after than, it slides left because your now going down the tree.

That is not to say that this wouldn't be a neat feature to add, but looking around the web, I couldn't even figure out if this is possible for browsers that support the history API, but for those that doesn't, it is certainly not unless we wan't to make awful workarounds.

from ui-router.

ksperling avatar ksperling commented on August 24, 2024

For history API, we could include a numeric value in the state and increase it on each forward transition. On a popstate we can then compare that number to the current one.

For legacy we could either not bother, or keep our own history (just an array of the URLs visisted within the current page, capped to some limit) and then when a state change is about to happen via $location, see if the URL we're going to is the last one we've been at.

from ui-router.

jeme avatar jeme commented on August 24, 2024

@ksperling Problem with the legacy approach is that if the user actually navigates to the same link (not by the back button), it's a forward navigation... E.g. he clicks "/page1" then clicks "/page2" then clicks "/page1" again.

If we base it on an "URL" history, that would see it as a "back"...

from ui-router.

timkindberg avatar timkindberg commented on August 24, 2024

Seems like the same thing would happen if you went page2, page1, then page2. I'm kind of thinking this feature is better handled with some logic of where the user is coming from compared against where they are going instead of relying on history which can be completely messed up if the user travels directly to a page.

from ui-router.

timkindberg avatar timkindberg commented on August 24, 2024

As a user I could attach a depth to states; so root would be 0 then children of root would be 1.0, 1.1, 1.2, etc. then children of those would be 2.0, 2.1, 2.2, etc. Then in ngAnimate if the state I'm going to has a higher depth number than the state I'm coming from (meaning its deeper or a its sibling that comes after) then play the "forward" animation otherwise play "backward".

from ui-router.

legomind avatar legomind commented on August 24, 2024

@timkindberg I think you have the right idea there. That logic would allow detection of peer-to-peer navigation as well.

from ui-router.

ksperling avatar ksperling commented on August 24, 2024

As basic requirement to support any of this ng-animate / $animator needs the ability to pass a custom "context" object for the transition through to the actual animation function, or ideally even the ability to choose between a set of animations declaratively.

from ui-router.

juanmarinbear avatar juanmarinbear commented on August 24, 2024

I am currently working on a website that could use this feature. I have six sections. If you go from section 1 to 6, you quickly go through the other 4. However, when you press back, history saves the last section you went through, 5. So instead of going back to 1 (your origin) you go back to 5. I will work on capturing the "Back" press event and do some logic on it but would love a cleaner solution.

from ui-router.

cudasteve avatar cudasteve commented on August 24, 2024

Here's my use case. I think it's one of the more common ones. I'm listening for $stateChangeStart to prompt for "are you sure?" to prevent leaving unsaved edits.

If the user clicks a link to leave the page, using $stateChangeStart, I can prompt them, get their response, and cancel the navigation if the user dictates. Then if they click the link again and this time say "OK I'd like to leave" I can just let them go through.

However, if we try that same workflow with the back button things are a little different. When they hit the back button, you can see the URL change to the toState. After prompting I can call event.preventDefault() to prevent them and UI-router will put the correct URL back, but the page they were originally trying to go back to gets removed from the browser's history. So if they hit back again and accept this time, it'll send them back two pages.

@mwager's suggestion would allow me to get around this relatively nicely by allowing me to essentially check for whether they hit the back button or not. If they did, I can just call history.pushState({}, ''), which will quickly re-save the page they were trying to go to (because the URL has already changed) before event.preventDefault() pushes the original state back up on top.

For now, I'm probably going to compare $state.href(fromState, fromParams) with $location.path() to determine if the back button was pressed. That should get me by but isn't very elegant.

....if that makes any sense.

It'd be really nice to have a "here's how you prevent the user from leaving a page with unsaved edits" best practice writeup for UI-Router that covers all the ways to leave a page state-change, link-click, back button, refresh button, and close button.

...oh and shoot what about the FORWARD button??? I can't think of anything to help with that.

And there's even less hope when the user selects an item from the history rather than just pushing the back button.

from ui-router.

cudasteve avatar cudasteve commented on August 24, 2024

FYI, in case anyone needs something like this in the future, this is what my final solution looks like that accounts for link-clicking, state changes, back button, reload button, and close button. The other two (forward button and history item selection) are a lot harder I think.

    // State change, link clicking, and back button
    $scope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
        if (!$scope.noSave  && hasChanged()) {
            if (confirm("Are you sure?\nUnsaved changes will be lost.")) {
                $scope.noSave = true;  // so subsequent redirects in this same state change don't ask again
            } else {
                if ($state.href(fromState, fromParams) !== $location.path()) {
                    // Clicked back button
                    history.pushState({}, '');  // Requires HTML5 pushState API
                }
                event.preventDefault();
            }
        }
    });

    // Refresh and close buttons
    $window.onbeforeunload = function () {
        return hasChanged() ? 'Unsaved changes will be lost.' : null;
    };
    $scope.$on('$destroy', function() {
        $window.onbeforeunload = undefined;
    });

from ui-router.

floyd-may avatar floyd-may commented on August 24, 2024

This StackOverflow answer seems to be far more complex than what @cudasteve has posted:

http://stackoverflow.com/a/22402285/170407

Is the SO answer overkill?

from ui-router.

cudasteve avatar cudasteve commented on August 24, 2024

@floyd-may I think the SO answer is answering something slightly different than my solution. My solution is just a way to implement "are you sure?" prompts when leaving states using the back button. My solution assumes the previous states have already been added to the browser's history via URL changes, whereas the SO answer seems to be about how to leverage the back button for navigation even without URL changes.

And neither of those things are the full scope of what I think is being discussed in this issue anyway.

from ui-router.

amypellegrini avatar amypellegrini commented on August 24, 2024

My case involves 404 redirection on certain routes. When a user (for whatever reason not relevant here) gets a 404 page, going "back" navigates to the same route that redirected to 404, which ends up again in a 404 page. I've tried to prevent pushing state for these cases, so the URL is not recorded in history, but fur some reason $state.go('notFound', {}, { location: false }) is not doing the trick, I'm not sure if this is actually a bug.

from ui-router.

stale avatar stale commented on August 24, 2024

This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs.

This does not mean that the issue is invalid. Valid issues
may be reopened.

Thank you for your contributions.

from ui-router.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.