2

In $stateProvider#state(), I define it as follows for Bootrtrap-ui modal using UI-Router. reference

var state = {
    name: 'modala',
    parent: 'home',
    onEnter: function($modal, $state) {
        modalInstance = $modal.open({
            templateUrl: 'modala.html',
            controller: 'modalaCtrl',
            controllerAs: 'modal'
        });
        modalInstance.result['finaly'](function() {
            modalInstance = null;
            if ($state.$current.name === 'modala') {
                $state.go('^');
            }
        });
    },
    onExit: function() {
        if (modalInstance) {
            modalInstance.close();
        }
    }
};

I want to use 'modala' any place other than home.

I do not want to create a lot of definitions of 'modala'.

Is there a method to accept it, and to set what is necessary in parent?


add explanation

No good solutions

  1. Don't set parent in modal state.

    result: when open modal window, parent isn't displayed.

    pattern 1 example

  2. modal state name is ${parent.name}.modal format.

    result: It's work. but, About one modal window, it is necessary to define many states. and, It is necessary to add a state whenever I add an parent who call modal.

    pattern 2 exapmle

  3. define the modal state every parent

    result:same as pattern 2.

    pattern 3 exapmle

Community
  • 1
  • 1
dayo
  • 35
  • 6

4 Answers4

1

All you have to do is add the property parent: modala to all child states that you define in order to set a parent state.

Aaron Leon
  • 116
  • 3
  • You might find this documentation to be helpful: https://github.com/angular-ui/ui-router/wiki/Nested-States-%26-Nested-Views – Aaron Leon Aug 19 '15 at 04:54
  • thank you Aaron Leon. But. 'modala' is not parent. 'modala' is unspecified large number of child.I don't write many many 'modala' state setting;( states = [{name:'home.modala', ...}, {name:'list.mocals', ...}, ... any..]; – dayo Aug 19 '15 at 06:17
  • 1
    I'm not sure I quite understand your question fully, but if you want to make an unspecified number of states that reuse the "modala" code, then you will want to treat "modala" as an abstract parent state and have all of your child states use "modala" as a parent. Would you mind providing the code you have for modala.html and modalaCtrl so we can get a better picture of what you're trying to do? And perhaps an example of the child states that you're trying to create. – Aaron Leon Aug 19 '15 at 19:51
  • Thank you. add example. I am glad when I have you look :) – dayo Aug 20 '15 at 07:54
  • So if I understand your question correctly, you have pages (for example, page1 and page2) and you want to put those pages into modal windows. The problem you're having is that you have to redefine a page1.modal state and a page2.modal state, and instead you want to just define modal once? – Aaron Leon Aug 20 '15 at 19:58
  • If that is the case, what I'm going to propose is that instead of using page1 and page2 as parent states, switch it the other way. Use modal as an abstract parent state for page1 and page2 and add a ui-view in the modal view where the contents of page1 and page2 should be placed. Take a look again at this link: https://github.com/angular-ui/ui-router/wiki/Nested-States-%26-Nested-Views And pay careful attention to abstract states at the bottom and the Plunker they provided – Aaron Leon Aug 20 '15 at 20:00
  • Thank you for comment. I think that you understood my question. but, I do not know how I use abstract parent state.;( – dayo Aug 21 '15 at 06:41
1

There is updated plunker (the second try from the question)

What we would see in action, is different use of decorator, as in detail described in my previous post

So, firstly, let's have few states e.g. 'home', 'page1', 'page2' ... and we would like for all of them introduce the child state - with modal functionality. That modal features are expected to be the same across all child states - but these will belong to different parents.

To make it happen we can use state definition like this:

.config(function($stateProvider) {
  // we just define empty child state for each existing parent
  $stateProvider.state('home.generalModal',  {});
  $stateProvider.state('page1.generalModal', {});
  $stateProvider.state('page2.generalModal', {});
})

And that could be enough, if we will hijack the decorator this way:

.config(['$stateProvider', 
  function($stateProvider) {

    var endsWith = function(stringToBesearched, valueToBeFound) {
      return stringToBesearched.slice(-valueToBeFound.length) === valueToBeFound;
    }

    $stateProvider.decorator('data', function (state, dataBuilder) {
      // this is original, by configuration created parent
      var data = dataBuilder(state);

      // we can define where we do not want to change that default, configured
      // in our case, we extend every state which ends with .generalModal
      var skipState = !endsWith(state.name, ".generalModal")

      // and return taht default
      if(skipState) 
      { 
        return data;
      }

      // the modal instance per this state instance
      var modalInstance;

      // definition of the onEnter
      var onEnter = function($modal, $state) {
          console.log("Entering state: " + $state.current.name)
          modalInstance = $modal.open({
            templateUrl:'modal.html',
            controller: 'modalCtrl',
            controllerAs: 'modalCtrl'
          });
          modalInstance.result['finally'](function() {
            modalInstance = null;
            if(endsWith($state.$current.name, ".generalModal")) {
              $state.go('^');
            }
          });
        };

      // definition of the onExit
      var onExit = function($state) { 
          console.log("Exiting state: " + $state.current.name)
          if (modalInstance) {
            modalInstance.close();
          }
      };

      // extend state with both of them
      state.self.onEnter = onEnter;
      state.self.onExit = onExit;

      return data;

    });
}])

We extended every child state which name endsWith ".generalModal" with onExit and onEnter. That's all. At one place...

Check it in action here

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • Thank you very much for your advice! This method realizes that I want to do it. I think to be able to do it in plural 'modal':) – dayo Aug 21 '15 at 10:18
0

There is a solution built inside of the UI-Router, called state decorator

decorator(name, func)

This way, we can create an aspect, which will be injected into any state we want later. That aspect, could drive some common, global setting. E.g. parent or views...

Check an example here: How to decorate current state resolve function in UI-Router? Current function isn't invoked, small cite:

Allows you to extend (carefully) or override (at your own peril) the stateBuilder object used internally by $stateProvider. This can be used to add custom functionality to ui-router, for example inferring templateUrl based on the state name...

There is a working example for our scenario

What we would need, is the decorator definition, like this:

.config(['$stateProvider', 
  function($stateProvider) {

    $stateProvider.decorator('parent', function (state, parent) {
      // this is original, by configuration created parent
      var result = parent(state);

      // we can define where we do not want to change that default, configured
      var skipState = state.name === "home" 
                   || state.name === "modala"
                      // child already has that in parent
                   || state.name.indexOf(".") > 0 ;

      // and return taht default
      if(skipState) 
      { 
        return result;
      }

      // FINALLY - HERE
      //   we want to change parent, or even introduce new
      state.parent = 'modala'; 

      // and rebuild it
      result = parent(state);

      // new parent in place
      return result;

    });
}])

Check that in action here

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • thank you for answer. 'modala' is not parent. 'modala' is child. I am sorry that my English explanation is not good. I think to make a sample because explanation is difficult. – dayo Aug 19 '15 at 09:20
  • Thank u. I did not know whether you came well, but added explanation. – dayo Aug 20 '15 at 07:52
  • I used your second try and did my best to show you how the above solution could be used in action. Hope now you have your answer ;) – Radim Köhler Aug 21 '15 at 06:54
0

I was wanting the solution to this too. I eventually worked it out.

See my stackoverflow answer / question

Community
  • 1
  • 1
dotnethaggis
  • 1,000
  • 12
  • 26