Angularjs UI bootstrap temporarily change URL on open and revert to original URL on close

空扰寡人 提交于 2019-12-22 07:12:09

问题


I want to temporarily change the browser url when the ui bootstrap modal is opened ( The page behind should remain as is, only the url changes ). When the modal is closed the url should be reverted back to the original one.

Steps :

  1. User loads the page
    • url : xyz.com/home
  2. User clicks a link opens a modal
    • url : xyz.com/detail/123
    • possible solution : changing url with html5 push state
    • problem : Angular ui-router tries to run its routes as per the changed url, eventually changing the background page.
  3. User closes the modal
    • url : xyz.com/home
    • possible solution : html5 pop state
    • problem : Reloads the background page, which kills the purpose

Example implementation : Pinterest pins and their pin details popup.


回答1:


You can use ui-router-extras sticky state to solve your problem. There is simple example with modal by the link. You should create two named views, one for main content (background) and one for modal.

<div ui-view="app"></div>
<div ui-view="modal"></div>

Mark the state, from what you want to access to modal as sticky: true in route definition.

.state('main', {
  abstract: true,
  url: '/',
  templateUrl: '_layout.html'
})
.state('main.index', {
  url: '',
  sticky: true,
  views: {
    'app': {
      templateUrl: 'index.html'
    }
  }
})
.state('main.login', {
  url: 'login/',
  views: {
    'modal': {
      templateUrl: 'login.html'
    }
  }
})

Also add an event for stateChangeSuccess:

$rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
  if ((from.views && !from.views.modal) || !from.views) {
    $rootScope.from = from;
    $rootScope.fromParams = fromParams;
  }
});

so, when you need to close modal, you can just

$state.go($rootScope.from, $rootScope.fromParams);

There is small problem for that solution. If you reload page on the modal state, then the app ui-view will be empty.




回答2:


This can be achieved by having a nested state and triggering the modal using onEnter callback:

$stateProvider
  .state('contacts', {
    url: '/home',
    templateUrl: 'home.html',
    controller: function($scope, MyService){
      $scope.contacts = MyService.getContacts();
    }
  })
  .state('contacts.details', {
    url: "^/details/:id", // using the absolute url to not have the "/home" prepended
    onEnter: function($state, $uibModal) {
      var modal = $uibModal.open({
        templateUrl: 'details.html',
        controller: function($scope, $stateParams, MyService) {
            // get data from service by url parameter
            $scope.contact = MyService.getContact($stateParams.id);
        }
      });

      modal.result.finally(function() {
        $state.go('^'); // activate the parent state when modal is closed or dismissed
      });
    }
  });

This technique is described in the ui-router's FAQ.

Here the plunk. In this example the modal's scope is created as a child of the $rootScope - the default $uibModal's behavior when no scope is passed to it. In this case we should use the service in the modal's controller to obtain the data by url parameter.

To have master and details URLs look like these - xyz.com/home and xyz.com/detail/123 - we should use the absolute URL (^/details/:id) in the child state.

Using this solution you can open the detail URLs directly and still have both, master and detail states, activated properly, so sharing the detail URL is possible.




回答3:


I think you can achive that with ngSilent module

https://github.com/garakh/ngSilent

using $ngSilentLocation.silent('/new/path/'); (once you open modal and again after closing it)




回答4:


Managed to implement this using https://github.com/christopherthielen/ui-router-extras/tree/gh-pages/example/stickymodal



来源:https://stackoverflow.com/questions/37598079/angularjs-ui-bootstrap-temporarily-change-url-on-open-and-revert-to-original-url

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!