Reinhard Poetz wrote:
Sylvain Wallez wrote:
Sylvain Wallez wrote:
Sorry to rain on the party, but the new widget state stuff in CForms should make building multi-page forms a piece of cake.
Off writing an example....
Done, I wrote my first wizard with CForms :-)
Please update branch 2.1.x and point your browser to http://localhost:8888/forms-samples/do-multipage.flow
Enjoy!
Great, thanks for the example! One question: IIUC the wizard is driven by the widget states and the event handling mechanism.
Yes: the various "pages" are widget groups (fd:struct) whose state is set either to active or invisible depending on the displayed page. The initial state, in the form definition, is to have only page1 being active, others being invisible. Navigation is managed by fd:action that change the page state. "next" validates the current page whereas "prev" doesn't. On the last page, a fd:submit goes back to flowscript if validation is successful.
This may solve many use cases but would it be possible to control which part of the form is shown by the controller (flowscript) which would bring some more flexibility (mix in non-forms pages, jump to different sub-pages)?
That is possible if you use fd:submit instead of fd:action when control has to come back to flowscript. Since only the active widgets are validated, the submit will be sucessful if the widgets in the current page are valid, not taking other pages into account. It's then the flowscript's responsibility to display the appropriate page when calling again form.showForm().
[some pseudocode ...]
var myFlow() {
var form = new Form("myForm");
form.load(myBean);
form.showSubForm("myPipeline", "../page1");
cocoon.sendPageAndWait("showAnotherPage");
form.showSubForm("myPipeline", "../page");
form.save(myBean);
}
The "showSubForm" above would simply set all pages to invisible state except the one defined by the second parameter (which should be "pageX" rather than "../pageX").
And while writing this, another question came up: What's the best way to deal with validation errors? example: On page 2 the users enters something that wouldn't let page 1 validate any more. Can we handle this?
Validation of the last page could revalidate previous pages in order, and switch back to the first one that doesn't validate successfully.
That could be something like:
function validateWizard() {
currentPage.setState(WidgetState.INVISIBLE); // another one may be chosen below
for (page in pageList) {
page.setState(WidgetState.ACTIVE);
if (page.validate()) {
page.setState(WidgetState.INVISIBLE);
} else {
return false; // validation failed
}
}
}
Setting the page state to active before calling validate() is important as non-active widgets are not validated. That isn't a problem here since we must redisplay a page that doesn't validate, but I'm thinking of adding a Widget.validate(boolean force) method, that would, when "force" is true, validate widgets whatever their state.
Sylvain
-- Sylvain Wallez Anyware Technologies http://www.apache.org/~sylvain http://www.anyware-tech.com { XML, Java, Cocoon, OpenSource }*{ Training, Consulting, Projects }
