Skip to content

Wildcard * parent state #1014

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
shmatul opened this issue Apr 9, 2014 · 13 comments
Closed

Wildcard * parent state #1014

shmatul opened this issue Apr 9, 2014 · 13 comments

Comments

@shmatul
Copy link

shmatul commented Apr 9, 2014

Each parent state on my app should be available to a child state named "deals/:dealId".
For instance:

state('parent.categories/:catId', {}) can load the 'deals' state:
/categories/clothing/deals/123

state('parent.search/:term', {}) can load the 'deals' state:
/search/nike/deals/123

and so on.

As for the current situation, I have to define the "deals" state for each and every available parent state:

state('parent.categories.deals')
state('parent.search.deals')

Now - maybe I'm not entirely focused on how ui-router works,
but this case has to be available on my app and I couldn't find any proper solution for it.

If I could use a wildcard state parenting that would be simple awesome:
state('*.deals');

BTW
I tried using a dynamic variable for the state name (currentState+'.deals') but it only catches the default currentState var that has been declared.
If I change currentState the 'deals' state won't be effective on the new current parent state.

Thank you.

@polyclick
Copy link

+1

1 similar comment
@orzilca
Copy link

orzilca commented Apr 12, 2014

+1

@timkindberg
Copy link
Contributor

This idea has been brought up before... #160. Not sure if that is the same. Basically a way to set up reusable "component" states, that can be attached wherever.

@polyclick
Copy link

Like for instance a photo overlay that should have a deeplink but has to be reusable throughout the whole webapp by defining its own state:

events/event-slug-1/photo/3
events/event-slug-1/photo/4
products/product-slug1/photo/1
products/product-slug1/photo/2
...

@timkindberg
Copy link
Contributor

Yeah, so that would be the "component" that I mentioned. That idea is not even in development at the moment.

@schmod
Copy link

schmod commented Apr 23, 2014

I think that #304, and #953 also touch on this same issue (and desire to have pre-defined child states/views that can be reused elsewhere throughout the hierarchy).

We may want to start consolidating these tickets, or create some sort of central design document to try to capture most of the desired use cases.

@schmod
Copy link

schmod commented Apr 23, 2014

This being said, I'm not sure that I like the idea of "wildcard" states, because deals would end up becoming a child of every single state within your application.

A better idea might be to require us to allow states to prototypically inherit, and require us to define where they can be used.

You could end up with this (pseudocode):

.state('deals', {
  url: '/deals',
  childOnly: true
  controller: 'DealsCtrl'
})
.state('categories',{...})
.state('.categories.deals', {
   inheritsFrom('deals')
})
.state('search',{...})
.state('search.deals', {
   url: '/dealSearch',
   inheritsFrom('deals')
});

Here, I'm introducing two new concepts, childOnly, inheritsFrom.

childOnly would be a close cousin of abstract, and declare that the state should not be a child of the root state (and, should only be accessible as a child state, to be defined elsewhere)

inheritsFrom simply states that categories.deals inherit its properties from deals.

This would allow us to nest and reuse entire state hierarchies (ie. if deals has children of its own), and also override properties of our reusable states on a case-by-case basis (as I did to the url property of search.deals above).

@jeme
Copy link
Contributor

jeme commented Apr 27, 2014

@schmod You should be able to get fairly close to that pattern with a custom provider.

Something like:

var base = angular.module('demo.base', [...]);

base.provider('statex', ['$stateProvider', function(sp){

  var templates = {};

  this.state = function(name, state) {
    sp.state(name, state);
    if(angular.isDefined(state.extend)){
      angular.forEach(state.extend, function(value, key){
        sp.state(name+"."+value, angular.copy(templates[value]));
      })
    }
  }

  this.template = function(name, template) {
    templates[name] = template;
  }

  this.$get = [function() {
     //No service, we could wrap the state service if we wished.
  }]
}])

base.config(['statexProvider', function(sp){

  sp.template('deals', {  
    url: '/deals',
    views: {
      counter: { template: { html: 'TEMPLATED DEALS VIEW' } }
    }
  })

}])

angular.module('demo.home', ['demo.base', ...])
  .config(['statexProvider', function(sp){
    sp.state('home', {
      extend: ['count'],
      url: '/',
      views: { 
          main: {  template: 'home.html'
        } 
      }
    })
  }]);

@anton000
Copy link

+1

@kri5t
Copy link

kri5t commented Mar 22, 2015

+1

I could really use this for a login modal, that I need to apply on different states, so the parent state doesn't change when I open the modal.

@joaoreynolds
Copy link

+1

@nateabele
Copy link
Contributor

Has anyone in need of this functionality taken a look at sticky states in UI Router Extras? https://christopherthielen.github.io/ui-router-extras/#/sticky

@eddiemonge
Copy link
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests