You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wicket.apache.org by Matt Jensen <ma...@picasystems.com> on 2007/09/25 18:00:51 UTC

Nestable Wizard Models

Hello, this is my first post to this list, so I apologize if this is 
going to the wrong place (the wizard support being in wicket-extensions, 
not in wicket itself.)

I have a use case where I would like to be able to splice wizard 
sequences together, possibly injecting one wizard into another under 
certain conditions.  Here is an example.  Say that I have a wizard 
process which creates Widgets, and every Widget must be associated with 
a Doohickey.  I want to allow the user to proceed down one of two paths: 
he may select an existing Doohickey, or he may choose to create the 
Doohickey on the fly.  If he chooses the latter, I would like to 
"splice" the "Create Doohickey" wizard sequence into the "Create Widget" 
sequence.  I want to share as much code as possible between the 
standalone Create Doohickey wizard and the embedded-in-Create-Widget 
Create Doohickey wizard.

This use case basically requires two things: first, the WizardModels 
must be defined in a standalone manner, so that Create Widget has the 
ability to create a Create Doohickey sequence and inject it into its own 
sequence. Second, the spliced-in wizard must only appear under certain 
conditions.  In this case, the condition would be that the user did not 
select an existing Doohickey earlier in the wizard sequence.

My current solution to this problem involves a new class which maintains 
a list of IWizardSteps outside of any IWizardModel; that object has a 
method which can be called to "inject" those wizard steps into any given 
IWizardModel.  As it injects those steps, it also applies a single 
condition across all of them...possibly merging it (using "and" 
semantics) with the ICondition implementation on the step itself.  While 
this setup works, and it does allow a single condition to cover several 
steps in a single model, it just feels "clunky."  I can't help but feel 
that a better way to do this would be to allow WizardModels to be 
nested, possibly linked with IConditions.  This would afford complete (I 
think?) reusability of models in this "splicing in" scenario.

Am I completely off base here?  Is there a better way to do what I am 
trying to do?  IDynamicWizardStep is obviously not an option because the 
"nested" wizards would not be aware of the steps/models before and after 
them.  IConditions alone won't do it because I'd rather not expose all 
of the steps in each sub-sequence to whatever super-sequence may contain 
it--and the conditions will change on a wizard-by-wizard basis.

If this does sound like a reasonable solution, or if somebody has a 
better solution, I'd like to know about it.  I would be willing to try 
to implement this and contribute it back to the project. 

--Matt Jensen


Re: Nestable Wizard Models

Posted by Kent Tong <ke...@cpttm.org.mo>.

Matt Jensen-2 wrote:
> 
> I have a use case where I would like to be able to splice wizard 
> sequences together, possibly injecting one wizard into another under 
> certain conditions. 
> 

Try using the attached RecursiveWizardModel. You give it a wizard model and
it 
is prepared to handle a step returned from that model which is a child
wizard 
model. The child wizard model is completely unaware of the enclosing model.

Some sample code:

public class RecursiveWizardTest extends WebPage {
	private MyStep stepA;
	private MyStep stepB;
	private MyStep stepC;
	private MyDynamicStep stepX;
	private MyDynamicStep stepY;
	private MyDynamicStep stepZ;
	private WizardModel secondLevelModel;
	private MyDynamicStep stepGroup;
	
	
	public RecursiveWizardTest() {
		stepA = new MyStep("a");
		stepB = new MyStep("b");
		stepC = new MyStep("c");
		secondLevelModel = new WizardModel();
		secondLevelModel.add(stepA);
		secondLevelModel.add(stepB);
		secondLevelModel.add(stepC);
		stepX = new MyDynamicStep(null, "x");
		stepY = new MyDynamicStep(stepX, "y");
		stepGroup = new MyDynamicStep(stepY, "unused") {
					public IWizardModel getWizardModel() {
						return secondLevelModel;
					}
				};
		stepZ = new MyDynamicStep(stepGroup, "z");
		stepX.setNextStep(stepY);
		stepY.setNextStep(stepGroup);
		stepGroup.setNextStep(stepZ);
		DynamicWizardModel topLevelModel = new DynamicWizardModel(stepX);
		topLevelModel.addListener(new IWizardModelListener() {
			public void onFinish() {
				setResponsePage(Completed.class);
			}
			public void onCancel() {
			}
			public void onActiveStepChanged(IWizardStep newStep) {
			}
		});
		Wizard w = new Wizard("w", new RecursiveWizardModel(topLevelModel));
		add(w);
	}
}

public class MyStep extends WizardStep {
	public MyStep(String label) {
		add(new Label("label", label));
	}
}

public class MyDynamicStep extends DynamicWizardStep implements
IWizardStepGroup {
	private IDynamicWizardStep nextStep;

	public MyDynamicStep(IDynamicWizardStep previousStep, String label) {
		super(previousStep);
		add(new Label("label", label));
	}
	public boolean isNextAvailable() {
		return nextStep != null;
	}
	public IDynamicWizardStep next() {
		return nextStep;
	}
	public void setNextStep(IDynamicWizardStep nextStep) {
		this.nextStep = nextStep;
	}
	public boolean isLastStep() {
		return nextStep != null;
	}
	public IWizardModel getWizardModel() {
		return null;
	}
}

http://www.nabble.com/file/p12898519/RecursiveWizardModel.java
RecursiveWizardModel.java 
-- 
View this message in context: http://www.nabble.com/Nestable-Wizard-Models-tf4516623.html#a12898519
Sent from the Wicket - Dev mailing list archive at Nabble.com.


Re: Nestable Wizard Models

Posted by Ryan Holmes <ry...@hyperstep.com>.
Think about presenting your "subwizards" in a modal window and  
keeping them decoupled from your main (i.e. top-level) wizard. For  
instance, in your main wizard's "associate a doohickey" step, the  
user could click a "create doohickey" link/button that would open the  
doohickey creation wizard in a modal window without leaving the the  
main wizard's current step. Obviously, the wizards need to  
communicate in some way, but that could be as simple as passing your  
main wizard's backing model (e.g. a WidgetBuilderBean) into each  
subwizard and letting the subwizard add to that model object in its  
onFinish method.

We wrote a shipment receiving wizard a couple of months ago and  
"spliced in" a subwizard to add shipment contents. Even though we  
added support for multiple overview bars to try to make it clear when  
you're in the subwizard instead of the main wizard, it's still a  
confusing UI in my opinion. In retrospect, displaying that subwizard  
in a modal window would be much more intuitive for the user and  
easier to implement. We'll probably rewrite it that way eventually...


-Ryan
On Sep 26, 2007, at 7:02 AM, Matt Jensen wrote:

>
> I don't think you're missing anything.  Yes, I could do that. :-)
>
> My real questions are 1) is there a better way, and 2) if not, and  
> if I were to implement this, does anybody have opinions on how to  
> set it up so that it will be useful to the widest audience  
> possible?  I imagine that somebody, somewhere, would have a use for  
> this functionality.  I would like to make it reusable and  
> contribute it back--the project deserves my help.  But I'm too new  
> to Wicket to be 100% certain that I know the "right way" to do it.
>
> That's why I posted to the dev list.  Plenty of folks here should  
> know the right/most widely applicable way to do it.
>
> Thanks for your response!
>
> --Matt
>
> Maeder Thomas wrote:
>>  Hi Matt,
>>
>> Perhaps I'm missing something, but why don't you just make your own
>> IWizardModel implementation? It would hold your wizard steps and
>> subwizards and map whatever behaviour you want to the IWizardModel
>> interface.
>> Thomas
>>
>


Re: Nestable Wizard Models

Posted by Matt Jensen <ma...@picasystems.com>.
I don't think you're missing anything.  Yes, I could do that. :-)

My real questions are 1) is there a better way, and 2) if not, and if I 
were to implement this, does anybody have opinions on how to set it up 
so that it will be useful to the widest audience possible?  I imagine 
that somebody, somewhere, would have a use for this functionality.  I 
would like to make it reusable and contribute it back--the project 
deserves my help.  But I'm too new to Wicket to be 100% certain that I 
know the "right way" to do it.

That's why I posted to the dev list.  Plenty of folks here should know 
the right/most widely applicable way to do it.

Thanks for your response!

--Matt

Maeder Thomas wrote:
>  
> Hi Matt,
>
> Perhaps I'm missing something, but why don't you just make your own
> IWizardModel implementation? It would hold your wizard steps and
> subwizards and map whatever behaviour you want to the IWizardModel
> interface. 
>
> Thomas
>   


RE: Nestable Wizard Models

Posted by Maeder Thomas <th...@ecofin.ch>.
 
Hi Matt,

Perhaps I'm missing something, but why don't you just make your own
IWizardModel implementation? It would hold your wizard steps and
subwizards and map whatever behaviour you want to the IWizardModel
interface. 

Thomas


> -----Original Message-----
> From: Matt Jensen [mailto:mattj@picasystems.com] 
> Sent: Dienstag, 25. September 2007 18:01
> To: dev@wicket.apache.org
> Subject: Nestable Wizard Models
> 
<snip....>
> 
> My current solution to this problem involves a new class 
> which maintains a list of IWizardSteps outside of any 
> IWizardModel; that object has a method which can be called to 
> "inject" those wizard steps into any given IWizardModel.  As 
> it injects those steps, it also applies a single condition 
> across all of them...possibly merging it (using "and" 
> semantics) with the ICondition implementation on the step 
> itself.  While this setup works, and it does allow a single 
> condition to cover several steps in a single model, it just 
> feels "clunky."  I can't help but feel that a better way to 
> do this would be to allow WizardModels to be nested, possibly 
> linked with IConditions.  This would afford complete (I
> think?) reusability of models in this "splicing in" scenario.
> 
</snip>