24

I use angular-ui-router and angular-bootstrap in my project.

I want to implement follow use case:

When user click to "edit" button, UI-Router change URL and open modal window. When I go back by click on browser's back button, modal window is closing.

If user reload page when modal window is opened, application should render modal window content in main ui-view container.

This use case you can see on this sire: http://canopy.co/ (try to click on item and reload page)

Question: How to implement behaviour described above?

Here is my jsFiddle http://jsfiddle.net/sloot/ceWqw/3/

var app = angular.module('myApp', ['ui.router', 'ui.bootstrap'])
.config(function ($stateProvider, $urlRouterProvider) {

  $urlRouterProvider.otherwise('/');
  $stateProvider
    .state('app', {
      url: '/',
      controller: 'AppCtrl',
      templateUrl: '/views/app.html'
    })
    .state('item', {
      url: '/profile',
      controller: 'ItemCtrl',
      templateUrl: '/views/item.html'
    });
})
.controller('AppCtrl', function($scope, $modal, $state){
  $scope.open = function(){

    // open modal whithout changing url
    $modal.open({
      templateUrl: '/views/item.html'
    });

    // I need to open popup via $state.go or something like this
  };
})
.controller('ItemCtrl', function(){});

2 Answers 2

19

There is a great example here on the ui-router FAQs. The key is using the onEnter param.

https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-open-a-dialogmodal-at-a-certain-state

Here's an example of to do it using ui-bootstrap's $modal service. This example only specifies an onEnter function. There is no template, controller, etc. So essentially the modal is shown, then when its closed it returns to the items state. You are still responsible for handling what state your app transitions to when the modal closes.

$stateProvider.state("items.add", {
    url: "/add",
    onEnter: function($stateParams, $state, $modal, $resource) {
        $modal.open({
            templateUrl: "items/add",
            resolve: {
              item: function() { new Item(123).get(); }
            },
            controller: ['$scope', 'item', function($scope, item) {
              $scope.dismiss = function() {
                $scope.$dismiss();
              };

              $scope.save = function() {
                item.update().then(function() {
                  $scope.$close(true);
                });
              };
            }]
        }).result.finally(function() {
            $state.go('^');
        });
    }
});
Sign up to request clarification or add additional context in comments.

3 Comments

This works great, but I see one issue. When I click somewhere on dark overlay around the $modal it closes itself, but it doesn't generate any event so state remains the same. Any idea how to fix this?
Found answer by myself. You should add second function callback in then (separate callbacks by comma). This second function will launch on dismiss and also when modal is closed by hitting Esc or clicking overlay.
BTW, it was updated to use finally instead of then in the FAQ you linked.
0

Here's an issue on UI-Router's Github describing what you're trying to do:

State transitions similar to Pinterest's overlay

You can see the implementation in this reply. Note though the way they were achieving the effect you want has been patched in the latest version and they're using an older version of UI-Router to maintain the functionality.

1 Comment

When I use 'preventDefault' function for '$stateChangeStart' event, ui-router doesn't change url. Do you know solution for change url and prevent view rendering?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.