Faheem Alam
Faheem Alam

Reputation: 525

Creating Stateful Modals in AngularJS with angular UI route and UI modal

I am trying to make a statefull modal using angular ui route and and angular ui modal.

lets say i want to fill a sign up form which consist of 4 pages. All of these pages are in a modal.

I am able to open modal on state change. But after that i want to open each pages of the modal on the bases of state.

    $stateProvider.state('signup', {
  url: '/signup',
  template: '<ui-view />',
  abstract: true
})
.state('signup.modal', {
  url: '',
  resolve: {
    modalInstance: function($modal) {
      return $modal.open({
        template: '<div ui-view="modal"></div>',
        controller: 'signUp',
        windowClass: 'signup-edit-modal',
        backdrop: 'static'
      })
    }
  },
  onEnter: ['modalInstance', '$timeout', '$state',function(modalInstance,$timeout, $state) {
    modalInstance.opened.then(function(status){
      if(status){
        $timeout(function(){
          // changing color of background / backdrop of modal for signup
          angular.element('.reveal-modal-bg').css('backgroundColor','rgba(255, 255, 255, .9)');
        })
      }
    })
    $state.go('signup.welcome')
  }],
  onExit: function(modalInstance) {
    modalInstance.close('dismiss');
    angular.element('.reveal-modal-bg').css('backgroundColor','rgba(0, 0, 0, 0.45)');
  }
})
.state('signup.welcome', {
  url: "/welcome",
    views: {
      modal: {
        templateUrl: 'main/signup/welcome.html',
        controller: 'signupWelcome'
      }
    }
}).state('signup.step1', {
  url: "/step1",
    views: {
      modal: {
        templateUrl: 'main/signup/step1.html',
        controller: 'signupStep1'
      }
    }
})

the above code able to open the modal and it also change the state to welcome but for some reason the template is not loading inside the modal. i have assign the template to a ui-view=modal it should open but not.

please help me. thanks in advance

Upvotes: 4

Views: 3619

Answers (2)

Faheem Alam
Faheem Alam

Reputation: 525

I have finally able to view the modal on the bases of state. I agree with @Obi Onuorah that the concept of modals is to hold the state and perform some action with requirement. But if you need to show the modal on the bases of state it is possible.

Thanks to awesome documentations of angular-ui route https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views#view-names---relative-vs-absolute-names which beautifully explains the different between the absolute naming vs relative naming of ui-view.

here is the sample code of UI route

    $stateProvider
  .state('list', {
    url: '/',
    template: '<ul><li ng-repeat="test in testObj"><a ui-sref="view({id: test.id})">{{ test.name }}</a></li></ul>',
    controller: function($scope) {
      $scope.testObj = testObj;
    }
  })
  .state('modal', {
    abstract: true,
    parent: 'list',
    url: '',
    onEnter: ['$modal', '$state', function($modal, $state) {
        console.log('Open modal');
        $modal.open({
          template: '<div ui-view="modal"></div>',
          backdrop: false,
          windowClass: 'right fade'
        }).result.finally(function() {
          $state.go('list');
      });
    }]
  })
  .state('view', {
    url: ':id',
    parent: 'modal',
    views: {
      'modal@': {
        template: '<h1>{{ test.name }}</h1><br />\
        <a ui-sref="edit({id: test.id})">Edit</a><br />\
        <a href="#" ng-click="$close()">Close</a>',
        controller: function($scope, test) {
          $scope.test = test;
        },
        resolve: {
          test: function($stateParams) {
            return testObj[$stateParams.id];
          }
        }
      }
    }
  })
  .state('edit', {
    url: ':id/edit',
    parent: 'modal',
    views: {
      'modal@': {
        template: '<h1>Edit {{ test.name }}</h1><br /> \
          <a ui-sref="view({id: test.id})">View</a> <br />\
          <a href="#" ng-click="$close()">Close</a>',
        controller: function($scope, test) {
          $scope.test = test;
        },
        resolve: {
          test: function($stateParams) {
            return testObj[$stateParams.id];
          }
        }
      }
    }
  });

i have made a simple plunker. http://plnkr.co/edit/hw9x7B?p=preview

Upvotes: 6

Obi
Obi

Reputation: 3091

That's the wrong way to do it.

You routes represent what state your application is in. The very concept of modals is to hold the state while capturing what might be an entirely separate process. What you should do is build your own step transitions for your modal and load the required 'template' for each transition into view using ng-if (I prefer this) or ng-show (there might be other ways).

If you want to use routes then don't use a modal basically.

Upvotes: 1

Related Questions