Skip to content
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

API to change a state parameter value and thus affect current state #86

Closed
stasgrom opened this issue Apr 15, 2013 · 13 comments
Closed

Comments

@stasgrom
Copy link

Hi guys,

I'm a bit lost in the following issue. We have a UI which we modeled using states, this UI displays a hierarchical structure of items (tree of items) from the left, and from the right there is a view that can display different aspects of a selected item. The URLs of states look something like:

/items/:id - default view of an item

/items/:id/details - detailed view of an item

/items/:id/details/attachments - attachments view inside the detail view

and so on, you get the structure. What I need, and currently don't find an API for in ui-router, is the way to change the :id parameter in the main state (the one responsible for the #/items/:id URL) as a result of item selection in the tree, and thus affect the current state without changing the other aspects of the state. For example if the item with ID 3 was selected and then the user changed selection to 7, I should move from URL:

/items/3/details/attachments

to

/items/7/details/attachments

Obviously this handling should be made in the topmost state, so I would expect some API like:

$state.current.update({id: 7})

But I don't see anything suitable.

Thanks in advance.

@jeme
Copy link
Contributor

jeme commented Apr 15, 2013

Not completely sure, but something close to this may work, @ksperling properly needs to adjust what I post a bit:

var params = angular.copy($stateParams);
params.id=7;
$state.transitionTo($state.current, params);

@ksperling
Copy link
Contributor

Yes, essentially currently you'll need to do something like that. We want to introduce a convenience API like $state.transition(...) though to make that simpler, but the syntax hasn't been defined yet (#15, even though the discussion on that issue has wandered way off that original issue).

Essentially the API will be something like $state.transition(stateOrNameOrShortcut, partialParams) where parameters that are not specified will be kept from the current state (if they are shared between the current and target state).

Apart from specifying an actual state object or name we want to have an easy way to specify

  • the current state
  • the parent of the current state
  • the partial name of a child of the current state (assuming the recommended dot-based naming is used)
  • the partial name of a subling of the current state (again assuming dot-based naming)

If you've got any thoughts on this or additional features you'd like to see in that API, let us know.

@ksperling
Copy link
Contributor

Maybe if the shortcut string starts with '.' it's taken to be relative to the current state, start with '..' to be relative to the parent, '...' for the grandparent etc, so that would make

  • current state: .
  • parent state: ..
  • child of current: .child
  • sibling of current: ..sibling

This should fit well with the recommended dot-based naming, and we could simply change the rules for valid state names to exclude any that start with '.' (and reject them in $stateProvider.state).

Thoughts on this syntax?

@timkindberg
Copy link
Contributor

I like that syntax, though more than two dots starts to seem a bit odd. .......details would be very hard to quickly read in code. It may actual not be good to mix dots as separators with dots as accessors. Dots work in folder paths because the slash is the separator. Hmmm, I'm not sure. I almost want to suggest something like ^ for parent (e.g. ^.sibling) but I don't like that either.

Perhaps we should consider not using dots as our separators?? That would be a fairly large change though and I like them in general. Maybe colon, e.g. contact:details.

@ksperling
Copy link
Contributor

I imagine you wouldn't really specify relatives paths more than two or at most three levels up as it would be pretty hard for anybody reading the code to follow what state you're referencing (no matter what the syntax is). I guess colon as separator is an option, stuff like '..:..:foo' looks odd as well though.

@timkindberg
Copy link
Contributor

ha yep your right, really only slashes work as separator and we don't want to use those because it relates to url routing too much. Dots should be ok.

@stasgrom
Copy link
Author

Thanks for sharing the plans. Looking forward to those APIs.

@jeme
Copy link
Contributor

jeme commented Apr 22, 2013

@timkindberg I am not sure I agree on that, after all '/' is merely a well known semantic of navigating tree structures... Think of XPath, File Browsing and yes well... Resource Locators (URL's), but that doesn't actually strictly tie to a tree structure funny enough >.<... also commonly used in breadcrumbs and so on... so '/' would be instantly recognized as something I could go up and down the state tree with in my mind... So I think it would make perfect sense to have:

. === current state
.. === parent state
../.. === parent of parent state
../other === child other of parent state
../[0] === first child of parent state
./[0] === first child of this state
./[-1] === last child of this state
/other === child other under root (this would be the state defined with: .state('other' {});
../../other/[3] === ehm... well you should get the navigation as of now >.<

And so forth in a very "XPath" style navigation, as that is already well known and well defined. Obviously supporting all the things XPath supports would properly not make sense.

@ksperling
Copy link
Contributor

@jeme '/' is obviously well-understood for tree structures, but I think the danger of people assuming that the URL structure and the state tree are essentially the same thing is too great when they will essentially look the same in simple cases. I think having a different syntax would be a good reminder that they're not the same and really not even similar in the context of ui-router.

@jeme
Copy link
Contributor

jeme commented Apr 22, 2013

@ksperling well I disagree. I think that if there is any confusion between states and urls, it will have arisen before they come to use the transitionTo function, and then they will get it cleared up at that point...

That said, I don't think there will be much confusion at all between the two, more like a "mention it ones and people will get it" sort of thing...

But that is just what I think.

Where as creating a whole new syntax might end up causing a bigger learning curve, depending on how much we end up with putting into it... I already have the above working and plan to add ways for "next sibling" and "prev sibling" in order to provide ease of use for wizards.

@ksperling
Copy link
Contributor

@jeme hmm, independent of the exact syntax, having an implied order between states sounds like it could be fragile, especially when they are defined by different modules where the order in which the states are defined depends on the order in which the modules happen to be bootstrapped.

If we really wanted to support something like wizards better (and I think even with having to name the siblings states explicitly for the prev/next links the whole thing would be pretty concise and readable), maybe we should consider the idea of named transitions again, so that you could do something like

$stateProvider
  .state('wizard.name', {
    transitions: {
      next: '..shipping'
    },
  })
  .state('wizard.shipping', {
  });

And then have a syntax like '!next' to do a look up of the transition of that name in the current state. At least that way it would generalize to things like transitioning from a 'display' state to the corresponding 'edit' state and back.

For any of this to save you any typing you're also assuming that e.g. the button that triggers the 'next' transition in your wizard is part of an 'outer' template shared by those wizard states. If the button is repeated in each wizard steps's template, you might as well just hard code the state name of the next step, and it would be more obvious what it does that way rather than implicitly relying on the order state definitions somewhere else.

@jeme
Copy link
Contributor

jeme commented Apr 22, 2013

@ksperling well I can't see that it would be fragile in any way, obviously it will hardly ever have another usecase than "wizzards" which is a usecase where you generally would define the states orderly and together.

You could still use "next sibling" where ever you would like, but that would hardly make sense and mostly give feel of "Random navigation"... But maybe I am mistaken here, maybe people would find other cases where it could be a useful feature, that doesn't mean it would break though.

And regarding expecting it to be in an outer template, well yes i would expect that in quite many cases, that said... using next/prev rather than hard-coded names means it is easier to push in additional wizard states at development, as you don't need to run around and correct the templates all the time, you just need to push in one more state.

@nateabele
Copy link
Contributor

This was partially resolved in #286. For the remaining issues (binding to $stateParams and updating without reloading), see #125.

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

5 participants