2

I am using UI Router 0.2.15 with Angular 1.4.3. Some of my pages can open a Twitter Bootstrap modal. By default, there is no way to link directly to an open modal, so I wrote a custom directive that will listen to a query parameter in the URL to open and close the modal. If the query parameter is present, it opens the modal, if not, it closes it. This comes in handy when users want to link to different modals on the same page, or simply want to deeplink to a modal. So buttons that used to trigger some JavaScript to open a modal now just link to a slightly different route instead that will open the modal through the directive.

This is handled by the following code from my directive:

scope.$watch(function () {
  return $state.params[param];
}, function (param) {
  $timeout(function () {
    if (param) {
      element.modal('show');
    } else {
      element.modal('hide');
    }
  }, 0, false);
}, true);

// When the modal is closed, remove the param from the URL
element.on('hidden.bs.modal', function () {
  $state.params[param] = undefined;

  scope.$apply(function () {
    $state.go($state.current, $state.params);
  });
});

This works fine, but here's my problem. Imagine the following flow:

  1. You open page a
  2. You open page b
  3. You click on a link to a modal at ?_id=1
  4. The query param _id=1 is appended, the modal is opened
  5. You close the modal, the query param is removed
  6. You go back in history
  7. It reopens the modal, since the last entry in history contains the query parameter

The modal is reopened, even though the user expects to end up on page a. After all, that was the last page the user visited.

In other words, how do I make the modal not have any effect on the browser's history, even though it's linkable?

My first idea was to replace the last entry in history whenever the query param changes. However, once the modal is opened, it's too late to do that, since I would need to access the second to last history entry and replace it with the current one, which, as far as I know, is impossible.

Ideally, there would be something like { location: 'replace' } on query parameter changes, that can be defined as another option in the routes.

I also checked Can you use hash navigation without affecting history? and AngularJS redirect without pushing a history state, to no avail.

Community
  • 1
  • 1
Dennis Hackethal
  • 13,662
  • 12
  • 66
  • 115
  • You could slightly change your approach as illustrated in this link https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-open-a-dialogmodal-at-a-certain-state . That should solve the browser history issue. – o4ohel Nov 03 '15 at 00:53
  • I think this is what you are looking for: [Answer](http://stackoverflow.com/questions/864633/assigning-to-document-location-href-without-clobbering-history) – Appeiron Nov 03 '15 at 19:32
  • @o4ohel Wouldn't that just add to the history as well? – Dennis Hackethal Nov 04 '15 at 18:38
  • @Charles The 3rd arg to $state.go is an options object which can have a location: 'replace' ... hope that helps. I'm doing something similar to you and it works for me. – o4ohel Nov 05 '15 at 01:12
  • @o4ohel What if someone directly opens the link? Then it's part of the history? – Dennis Hackethal Nov 05 '15 at 05:25

0 Answers0