cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Daniel Fagerstrom <dani...@nada.kth.se>
Subject Re: CForms Wizards
Date Wed, 17 Nov 2004 14:50:29 GMT
Sylvain Wallez wrote:

> Daniel Fagerstrom wrote:
>
>> Sylvain Wallez wrote:
>>
>>> Daniel Fagerstrom wrote:
>>
<snip/>

>> Sure, IMO, you should always do a complete validation of _all_ 
>> widgets before binding your form model to business data. There is the 
>> same problem with widget states, you can have faulty event logic so 
>> that you happens to hide some subtree during all states in the 
>> filling in of the multi form.
>
> Sure, but forgetting a whole subform within the event handling is less 
> likely to happen than forgetting a single widget in the template.

The complete validation will let you know if there is a forgotten field.

> Furthermore, we can automate the subform navigation and validation, 
> not only using <fd:wizard-action> but also using a new <fd:wizard> 
> container that would automatically iterate among its children (which 
> are likely to be <fd:struct> themselves).

Might be. The important question is IMO how to separate the different 
concern areas in multi page forms. My view is that:

* What you want to show in each sub form is a view concern and should be 
handled of the view layer e.g. JXTG with taglib.

* The control of the sub form flow is a control concern, and should be 
handled by the control layer, i.e. flowscripts.

* The model is responsible for the data structure and validation. In my 
view the widget hierarchy should mainly be responsible for model concerns.

I'm of course aware of that there are gray areas where it is hard or 
maybe impractical to place a functionality in M, V or C. But I find it 
hard to be entusiastic about evolving the form definition to a mix of M, 
V and C concerns.

>> So, partial validation is used after each sub form in a wizard to 
>> give immediate feedback. Then complete validation is done before 
>> using the data. This is IMO the only safe option.
>
> Exactly. But with template-driven wizard, you don't know where to go 
> back if validation fails, whereas with definition-driven wizard, we 
> simply redisplay the first invalid subcontainer. Or will you keep the 
> list of used widgets with each step to find where a widget was firstly 
> used?

You should never be alowed to pass an invalid sub form, you can go 
backwards from it not forward. Or are you thinking about some 
backtracking engine where the user fill in a value in sub form 10 that 
not is consistent with something on sub form 2 that makes sub form 2 
redisplayed and then the user have to try to go through the sub forms 
again. In that case: to much magic for my taste.

>>> Also, this behaviour only validates terminal widgets and no 
>>> container widgets, which may carry some additional semantic checks 
>>> like row uniqueness in a repeater.
>>
>> I'm aware of that as you can see in the bugzilla comment, and have 
>> not thought that much about of it yet. One possibillity could be to 
>> let value change "bubble" and let the container validators trigger on 
>> child events. Any other ideas? I have not used container validators 
>> yet, so I don't know that much about the use cases.
>
> The current behaviour is recursive depth-first validation, i.e. a 
> container triggers its own validators if all of its children are 
> valid. I'm not sure bubbling could do the trick, as validation is 
> handled separately from value-changed events, and we have to know 
> where to stop bubbling. Bubbling up to the Form is likely not to work, 
> as validation will fail on required fields that weren't in the template.

What I mean is that container validation is trigered by validation event 
bubling. If you introduce container level bubling you must of course 
design your UI so that you are able to fill in the fields within the 
container and see the validation error in the same screen.
 
<snip/>

>> If we can find a good solution of the parent validation problem, it 
>> is rather usefull as we only need to tell about what widgets that we 
>> want to validate once, in the view. Furthermore, even if I have no 
>> immediate need for that, Jonas has shown that it makes it safe to use 
>> a form frame work without having a form model in between the view and 
>> the "business data".
>
> Uh, no form model and still safe? I missed that...

Yes, and you can do more cool things. In Chiba they use an adapter in 
the view that replaces the XPaths in the HTML output from the view with 
some kind of  random identifyers and register the mapping in a lookup 
table, that is used in the request processor. In this way you have no 
info about the model at all in what you send to the browser.

>>> Furthermore, flowscript back-button magic implies that we can only 
>>> navigate back to the previous screen, and not in an arbitrary screen 
>>> in the sequence.
>>
>> I implemented it in that way because I didn't had any use cases for 
>> something more complicated. But you can send a "go back" message 
>> together with a web continuation id to the form handler, by using 
>> that the form handler can first save the current form data and then 
>> jumping to any previous continuation. I'll explain the details in the 
>> above promised "back-button magic" RT.
>
> Things I don't like in this back-button magic:
> - not all forms are wizard, rather the contrary. So having the wizard 
> engine plugged in deep in CForms doesn't seem good to mee.

It will not disturb you if you don't use it.

> - it's magic, meaning the fact that the user can go back is even not 
> apparent in the flowscript.

We can add pluggable event handlers in the form handler so that the user 
can plug in other control flow events.

> - it is limited to CForms only, meaning if other pages are placed 
> inbetween (regular pages, other form handling, etc), they cannot 
> participate in the wizard navigation.

In the implementation I provided, it should be possible AFAIK.

> We had such a discussion one year ago and at that time I proposed a 
> wizard API [1] that makes use of bookmarks and PageLocal (that did not 
> existed at that time). Such a wizard API would make the fact that a 
> wizard-style interaction is setup explicit in the flowscript, without 
> requiring much more coding, especially if we integrate CForms in the 
> wizard API (rather than putting wizards in CForms).

<snip what="example"/>

> This approach allows to use wizard-style navigation with any kind of 
> page, and not only forms. And if we want to go further, we could even 
> make wizards a built-in feature of flowscript, i.e. add some methods 
> to the "cocoon" object such as:
> - cocoon.startWizard()
> - cocoon.wizardStep(name)
> - cocoon.finishWizard() // to invalidate all continuations in a wizard
>
> The backwards navigation could then be handled automatically by the 
> sendPageAndWait() method. Yes, that would be magic as you'll have 
> nothing special to write, except "cocoon.startWizard()", which 
> implictely says "let's start the magic, I know it will happen from now 
> on".

An excelent idea, I will give it a look. I would also prefer to have 
some kind of high level library for different flow cases. The low level 
coding with continuations is far to complicated and error proon. 
Continuations are like gotos on steroids. They are excelent for 
implementing high level control structures, but the user should not need 
to know about them or use them.

<snip/>

>> Either you decide what should be shown together in the view or in the 
>> model. You get <jx:if> (or separate templates), in the first case and 
>> fd:structs in the second. IMHO it is better to code view aspects, 
>> like what should be shown in the same sub view, in the view than in 
>> the model. It will be easier to reuse the model for several views, 
>> e.g. specialist view (one screen), wizard view and pda wizard view, 
>> if you don't put the view groupings in the model.
>
> Mmmh... I agree and disagree at the same time :-)
>
> The various widgets that will be presented in a multi-page navigation 
> will be grouped by their relations, i.e. a page will show a consistent 
> set of related data. And when displaying the same data in a single 
> page, it's very likely that the same grouping will be used to lay out 
> the page, using e.g. <fieldset> elements.
>
> In that case, the difference between the multi-page and single-page 
> templates will be that only one of these groups will be visible a one 
> time in the multi-page template.

Grouping of data is a good thing. But it is not obvious how to create a 
hierachic grouping of the data for two different wizards in such away 
that you get one group per sub form.

<snip/>

>> :) So we booth belive that multi chanel wizards mainly should affect 
>> the view. But you want AFAIU to have event based flow control in the 
>> model and I prefer to have flowscript based flow control.
>
> The event-driven model allows to have the *exact same* flowscript 
> whether the form is displayed in a single page or across multiple 
> pages. This is important in a multi-channel application as, although 
> the view will be different, the application logic should be the same 
> whatever kind of browser the user has.

Flowscripts where introduced in Cocoon for describing page flow so you 
are not supposed to reuse the part of your flowscript that describe the 
flow as that happen to be _the description_ of the page flow.

<snip/>

>> A problem with coding where we are in the wizard, booth as a widget 
>> state and a flowscript state (i.e. where we are in the form handling 
>> loop), is that previous continuations might get inconsistent. What 
>> happens if the user happens to use the browser back button in a 
>> widget state based wizard e.g.
>
> Using a single continuation within the form.showForm loop (which would 
> therefore no more be formally a loop) may be a way to handle this.

Tried that in my form.showForm loop, (that is implemented that way), and 
the browser backbutton behaviour is still flawed.

/Daniel


Mime
View raw message