-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Submitted for discussion: Transitioning between specific states, and Ember.TransitionState #779
Comments
I don't think this is a crazy idea. I am probably one of the people in the channel that was asking if this existed somewhere. My needs are exactly as outlined above, the UI changes based on state and knowing where I came from and where I am going would really help when applying visual transitions. |
Edited the first of my two questions to more closely align with what I'm actually wondering: whether I'm making a mountain of a mole-hill, vis-a-vis the conceptual problems with knowing the previous or next state inside the enter/exit handlers. |
Can you not make the transition just a state itself? Like for animation. ViewingPeople -> SlidingLeftToPerson -> ViewingPerson -> SlidingRightToPeople -> ViewingPerson because your transition is a state you enter that connects the other 2 states. If you follow the pattern that only state events call gotoState this allows guards what states can transition to what state. |
I agree that simply adding the additional state and moving on and washing your hands of it suffices. My only concern with that, perfectly acceptable, solution is that it begins to weigh down the primary purpose of your statechart by forcing the manual insertion of states, and calling the transition into the guard state instead of the transition into the state you actually want to end up in. I think this is a particularly valid concern when the state transition in question is purely for UI, or is otherwise orthogonal to the other concerns at play in laying out your states. The idea behind a TransitionState API would be to allow you to hook into those more concrete state transitions in a transparent way, rather than 'pollute' the statechart with a bunch of accessory states, just for the sake of flattening everything out. |
States are supposed to be stateless, they represent a state of being. My app sends viewPerson(id) it doesn't know about the transition. The event handler in the state sets the personcontroller and calls goto SlidingLeftToPerson, enter state on that slides in the Person UI sends a complete event to the state which then calls goto ViewingPerson. The button that started this just sent viewPerson. These 'accessory' states might receive events that could interrupt a transition and it needs to unwind through its exit state, like a history back button. I don't think it is polluting the state chart so much as it is being honest about the complexity of your app. |
I'm sorry, I've had this same struggle in my head, is the idea that it would save boiler plate in setting up but that they'd still be a state? maybe have an abort and complete events? Please don't close this, I wasn't trying to be dismissive. |
I must confess I do think I misread some of your question probably because of haste and a little tiredness. And have struggle a lot with this issue with routing and animations in our app, so I've stewed on it a lot. I do think there is an idea here that could simplify a lot of boilerplate. Question, sometimes a transition from A->B can be different depending on the event that kicks it off? Like routing via the browser forward button might want to cut directly vs in app open button animates the transition. |
I'm sorry for being a bit short tempered, long day... So, moving on: my thinking behind TransitionState isn't to make the transition not a state. Rather, the couple of times I've told people the "your transition is actually a separate state and you should model it that way" solution I've gotten some push back, probably because creating states can already be kinda verbose and adding additional boilerplate, as you say, for what they see as a natural and somewhat consequence-free extension of their 'logical' statechart seems onerous. So, my thinking was, if you could lightly layer an additional API on top of the state creation, to transparently define a state to get inserted between a set transition from a given state A to a given state B, that sort of 'UI-only' state work could be implemented without it requiring people to rewire their statecharts, and also by allowing those transitions to be swapped out easily. It would, basically, turn the 'edges' in the chart into full states, on a selective, ad hoc basis. The downside is it does deformalize the statechart, a bit. Going from State A -> State B would no longer be 100% guaranteed to result in exit state A followed by enter state B. |
My thinking is somewhat influenced by having used Acts as state machine, which does model transitions between states as separate structures from states themselves. I think that's a bridge too far, and these transitions DO properly belong as states, but the mental model of 'upgrading' a transition to a full state without having to rewire the chart itself has some currency, I think. |
You're modeling the transition, it seems, and not the actual state. Possibly the naming of this as TransitionState is holding this back, since the transition is not a state, but obviously involved? Also, this seems like exposing the actual state transition which seems logical, but sort of strange. ie.
|
Well, from the developer's perspective you're in fact dealing with it as a transition between two states, but the internal implementation would be a full state that is transparently insinuated between the two states you're transitioning between. |
The importance of being a 'full state' being that it would accept events and such as if it were explicitly constructed in the state chart and gotoState('your_transition_state') had been called. So, as per @kselden's example, 'escape' could be trapped to cancel the transition. One additional, fairly minor, advantage over just hardcoding in the intermediate states into the statechart is a single TransitionState (or just Transition if that's a better name) could be bidirectional. The Transition would, by definition, be exempt from the requirement that it not know whence it is coming or going. |
I've definitely started to run in to this as well, and I agree that some sort of transition framework would be nice. Here's a shot in the dark: MyStateManager.transition('stateA', 'stateB', function() { /* do animation */ }); Or potentially (more verbose, but more ember-ish): Ember.StateManager.create({
// ...
transitions: {
AtoB: Ember.transition(function() {
// called when entering stateB from stateA
}).from('stateA').to('stateB'),
enterB: Ember.transition(function() {
// called when entering stateB from anywhere
}).to('stateB')
}
}) I'm not sure if naming transitions is too much overhead, or whether it would be useful. |
One thing to consider is that currently a view is removed when its corresponding ViewState is exited and added when it enters. If a transition from A -> B needs to perform some animation on A's view, then it can't exit before the transition starts/ends. However, if a transition from A -> B needs to perform animation on B's view, then likewise it needs to have entered B before the transition kicks in. If a transition was modelled as the period between A -> B, then it would have access to neither view because A would have already been removed and B not yet added. |
@jayferd My thinking on API was a simple extension of the current way statecharts are laid out, "simple" so it doesn't add too much verbosity, and "extension" so that it isn't an alien concept. Something like:
Additionally I am of the opinion that not caring about the particular state you're transitioning from means there is no additional state information needed, and you're probably doing something conceptually 'off' if a regular enterState handler isn't sufficient. @rlivsey Last I hear ViewStates were being deprecated. Either way, that automatic view adding-removing behaviour would be considered incompatible with animating those views manually in a Transition, much as it would be incompatible with manually transitioning those views using an explicitly defined in-between state. Although, I suppose it could be modified to detect if it's exiting into a handled transition, and in that case disable the automatic behaviour, in anticipation of the developer manually handling it. |
Just to confirm, ViewStates have been deprecated. |
This is pretty moot at this point with all the stuff that has happened over the past 6 months. |
…eprecation Add array observers deprecation
Every now and then someone on the channel wants to know how to find out in an enterState handler what the former state was, or what the next state is going to be in an exitState handler. Their reasons are compelling: they need to mutate their UI, and how their UI changes depends on the particular change in their app state.
My position has been that, basically, knowing what state you used to be in inside another state is extra-state information. It's another layer of state existing outside the formalized state chart. I liken it to the following scenario:
(1) The object is a Person
(2) State A is "At Home." "At Home" as an enterState action of "take off your shoes."
(3) State B is "At Work."
(4) State C is "On Vacation."
My argument is that if you want to do something when a Person transitions from "On Vacation" to "At Home" (say, disable the security system), you're not in either "On Vacation" or "At Home" states (and definitely not in "At Work," which is there simply to make the statechart non-trivial). That is to say, merely knowing that you used to be "On Vacation" means that there's enough additional state that you're not quite "At Home," either. What you are in is a transitory state "Transitioning from On Vacation to At Home."
If you follow this chain of logic, the conclusion isn't all that great: it basically requires that, anytime you want to distinguish between specific state transitions, that you use an intermediary state, that you manually create and handle moving in and out of:
My ideal solution is a special kind of state, TransitionState, that will be auto-transited when you call gotoState from its origin state to its destination state. That is to say, if you have TransitionState(A => B), and call gotoState(B) from StateA, the TransitionState will be entered and exited, allowing the proper state-aware encapsulation of the desired behaviour. The key, here, being that each state doesn't have to know about the intermediate transition states. When you want to go from StateA to StateB, you just call gotoState('StateB') from StateA and the transition is handled transparently.
Two questions:
(1) Am I just crazy, and having the ability to know the previous or forthcoming state inside an enter/exit handler isn't that big a problem, in terms of being properly stateful?
(2) If not, Is this a reasonable solution, or is it a distinction without a difference?
Further thoughts on this issue in general, or other proposed resolutions, are welcome as well!
*Edited to clarify a few things
The text was updated successfully, but these errors were encountered: