I'm making a wizard with multiple stages, all being submitted to the
same action. The stage is in the URL like:
/somestageofwizard/
/anotherstageofwizard/
etc.
Each wizard stage has a form, and need to be validated. However, I
only want each stages' validators to run on that stage. What is the
best way of going about this?
I have tried using regex validators for "stagename": each test against
a particular stage name, and "provide" a dependency to the validators
specific to that stage. However, this always results in the
"stagename" being marked as invalid, as it can only satisfy one of the
regex validators. I would like a way to "provide" a value that is
equal to the submitted stagename: this would allow attributes like
depends="somestageofwizard"
in the validator definitions, to ensure they only run on their stage.
Is there someway to do this? Is there maybe a better way?
Michal.
_______________________________________________
users mailing list
us...@lists.agavi.org
http://lists.agavi.org/mailman/listinfo/users
felix
--
Felix Gilcher
Bitextender GmbH
Paul-Heyse-Str. 6
D-80336 München
T: +49 89 57 08 15 16
F: +49 89 57 08 15 17
M: +49 172 840 88 28
felix....@bitextender.com
http://www.bitextender.com/
Amtsgericht München, HRB 174280
Geschäftsführer: David Zülke, Florian Clever
> Why don't you use separate Actions for each stage?
I was hoping to have things a bit more general: on this site there are
in fact 2 separate wizards for different (but related) things. Plus,
each stage is presented very similarly, and goes through a very
similar action: validate the input, and go onto the next stage. It
seems a bit non DRY to have each stage as a separate action. But would
that be the preferred solution...?
There's a pretty good writeup about DRY in german here: http://www.ruby-mine.de/2009/5/27/repeat-yourself-hin-und-wieder
felix
--
Felix Gilcher
Bitextender GmbH
Paul-Heyse-Str. 6
D-80336 München
T: +49 89 57 08 15 16
F: +49 89 57 08 15 17
M: +49 172 840 88 28
felix....@bitextender.com
http://www.bitextender.com/
Amtsgericht München, HRB 174280
Geschäftsführer: David Zülke, Florian Clever
However, I think I do disagree with what the "functionality" is in my
case. I would say the the functionality is:
"Validate the input for the current stage, save the data, and move to
the next stage"
But also: having a different action for each different stage would
make it trickier to add stages later. Right now I have that stages
defined in some simple php "config" code (order of stages, "nice"
names of stages etc...), with associated template files for the forms
themselves (It's a mild hack, but I think I can live with it). To
add / remove stages later I can edit these files. If each stage is a
different action, I would have to create a new action.
Michal.
There is no way of providing a dependency depending of the value of
the incoming value, a dependency is provided if the validator returns
"true". So there's some hacks that you can use - you could have
multiple validators, one for each value. You'd have to set the
severity to "info" so that the field is not marked as "failed". That
way each validator provides a unique dependency that you can depend
on. It's a bit hacky but it should work.
felix
I think I agree that it might not pay off, especially if it was very
tricky to do, but I think as a rule I like to keep in mind how to
generalise / make something "more dynamic" later. I think an action
per stage immediatly creates a stumbling block on how to generalise:
say if this were to be extended to a be a CMS where a user constructed
the wizard in a GUI.
> There is no way of providing a dependency depending of the value of
> the incoming value, a dependency is provided if the validator returns
> "true". So there's some hacks that you can use - you could have
> multiple validators, one for each value. You'd have to set the
> severity to "info" so that the field is not marked as "failed". That
> way each validator provides a unique dependency that you can depend
> on. It's a bit hacky but it should work.
That's actually less hacky than the way I've done it (and I
deliberatly don't mention the way I've done it...). I didn't know you
can set severity to "info" so it doesn't fail: that's very useful.
Thanks!
<validator class="equals" severity="info" provides="step1">
<argument>stagename</argument>
<ae:parameter name="value">stage1</ae:parameter>
</validator>
<validator class="equals" severity="info" provides="step2">
<argument>stagename</argument>
<ae:parameter name="value">stage2</ae:parameter>
</validator>
... etc, and then use depends="step1" and so forth.
However, there is a much better way that most people use:
<route name="products" pattern="^/products" module="Products">
<route name=".create" pattern="^/create">
<route pattern="^$" action="Create" />
<route name=".step1" pattern="^/step1$" action="Create"
method="step1" constraint="write" />
<route name=".step2" pattern="^/step2$" action="Create"
method="step2" constraint="write" />
</route>
</route>
Products_CreateAction::executeRead() brings up the first form and
POSTs to .step1, which will run Products_CreateAction::executeStep1();
on Success, you show the second form in there which submits to .step2,
which will run Products_CreateAction::executeStep2(), and there, in
the third form, you submit to .create (!), which will run
Products_CreateAction::executeWrite().
Keep in mind that you either need to store the intermediary step
values in a session or populate hidden fields.
This has several advantages:
- you can still POST to /products/create, e.g. for an API, without
going through the wizard steps
- all the responsibilities for actually creating the product are in
executeWrite(), so you can add other means of access (the
aforementioned API, or a SOAP interface etc etc)
- in the validation config, you can do <validators method="step1" and
so forth to group things.
Hope that helps,
David
Ah changing method is quite cunning! I didn't realise it could be
anything other than read or write. Although it does require
modification of the action for when adding stages, this does seem good
if stages are more "unique" in some way, as executeStepX method would
deal with that.
Thanks!