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.
The 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