Is there a better approach to the whole problem (ignoring disabling the buttons and client side validation)
Yes. The pattern is not being implemented correctly from what I'm reading.
Your "list of orders" screen should have it's own state-handling object.
This is a
context class/object as seen in the state pattern class diagram.
OrdersList sets its overall state based on user selections, button clicks, etc. Every user UI interaction triggers the
OrdersList state object to validate - because after all the UI state just changed - and set internal booleans that tell us what states are OK now. Each specific boolean is wired into the UI via the
context object, so selecting a (cancelled) order triggers
context validation which knows
cancel is not a valid next state and sets the "cancel boolean" to false. This boolean directly sets the Cancel button and voila.
States Do Not know how or if to allow other States
That's part of the point of the state pattern.
A given state knows how to validate itself. But how can it know what the next valid states are without some context? That context is the "list of orders" screen. Other screens in your app are also "context" of another kind. How in the world can every State object/class know about every button and user interaction possibility for the whole application? They cannot! Each context may have differing rules about what states are allowed. That's what the
context class is about.
If I validate before transition do I still need exceptions in the model?
In the model / context object yes. In each State, no.
Since I expected that this illegal transition action to occur would a validation before attempting to Cancel the line be more appropriate?
The question is moot now that we see every screen as having it's own state. So: The user doing anything in the UI changes then we must validate its new state - that's the
context object in action here. That context object validation sets UI controls so that only valid things are allowed.
A key is that all validation, all of it, is in your Model
The UI, client side, may have a modicum of validation but all logic necessary for determining state must be in your "behind the UI" model. Your
context object looks at what's been clicked, selected, etc. and the
context decides what to do.
If you're thinking that
context might also be the
Controller in the
MVC pattern, I suspect you're right