bselfridge (6) [Avatar] Offline
#1
I'm trying to make a special kind of web form. Early on, the user will define the parameters for the form, essentially implemented as a list that's persisted in a PostgreSQL database. Then, after they've defined that list of parameters, they will be able to fill in the form with specific values. This is all essentially working, but the rub is this: I want the user to be able to define what _type_ of input each parameter gets, whether it be TextField, DropDownChoice, or what have you. The user can currently input this information, but it isn't actually used yet. Right now, when the user goes to the form page, all the fields are TextFields by default:

parameters = new ListView("parameters", task.getTaskParameterList()) {
@Override
protected void populateItem(ListItem item) {
TaskParameter param = (TaskParameter) item.getModelObject();
item.add(new Label("paramName", param.getParameterName()));
item.add(new TextField("paramValue", new Model()));
}
};

The information about what type of input each parameter should have is in the method TaskParameter.getInputType(), which returns a String. In the populateItem method I want to interpret that string and add either a TextField or DropDownChoice, depending on what getInputType() returns. The problem with this is in the HTML. I either want to have an <input type="text"> tag or a <select>, but the HTML is pretty static with Wicket. Is there any way to accomplish this?

-Ben
Eelco12 (100) [Avatar] Offline
#2
Re: dynamic web components?
Yeah, you typically do this through panels. From the top of my head (I'm flying right now, and don't have a digital copy of WIA with me here) the chapter on custom components talks a bit about this. You basically create a panel for a text field, and a panel for a drop down, and insert the one you need dynamically. Once you get the hang of working like this, Wicket opens up a whole world of dynamic behavior for you smilie

Alternatively, you can create a custom component that writes out it's raw string either as input or select, but that'll probably require you to write much of the plumbing code that is already coded in the TextField and DropDownChoice components, so I don't necessarily recommend that other than as an exercise to get comfy with the Wicket framework. In that case, you'd overwrite Component's onComponentTag method. See the TextField and DropDownChoice components' source for some ideas on how to do that. This is talked about briefly in WIA as well actually, though without the book here I can't remember where.

Good luck and have fun.
bselfridge (6) [Avatar] Offline
#3
Re: dynamic web components?
Wow, thanks - that was incredibly helpful. I'm going to give it a shot now.
bselfridge (6) [Avatar] Offline
#4
Re: dynamic web components?
Yup, that was exactly what I needed. Eventually I'm going to have to start retrieving and persisting data from those dynamically generated fields, though, and I'm not quite sure how to go about doing this. Should I use the getList() method from ListView, and then use MarkupContainer's iterator to iterate through the form elements contained in each ListItem? This seems somewhat klugey, but maybe it's not that bad.
Eelco12 (100) [Avatar] Offline
#5
Re: dynamic web components?
Take a look at the chapter on Wicket & databases (chapter 13?) and the accompanying example code (http://wicketinaction.googlecode.com/svn/trunk/book-wicket-in-action/src/main/java/wicket/in/action/chapter13/dbdiscounts/ etc) to learn about how to work with databases. Additionally, there should be one or more examples of working with database with Wicket in the wicket-stuff project, for instance http://wicketstuff.org/confluence/display/STUFFWIKI/wicket-phonebook.
bselfridge (6) [Avatar] Offline
#6
Re: dynamic web components?
Actually, I already have a working Hibernate database - the problem I'm facing is like this:

1) Let the user define the fields in the form, along with the input type (done)
2) On another page, display a form built up from the user's custom fields and input types (done)
3) When the user submits the form, stick each form element into a table which has columns for the value they have entered and the ID of the "parameter" that value is associated with (each parameter is persisted in step 1) (not done yet)
4) On another page, display a list of parameter-value pairs, representing the user's input in step 3

So in step 2 I have a nice dynamic form that you helped me create, generated by this code:

parameters = new ListView("parameters", task.getTaskParameterList()) {
  @Override
  protected void populateItem(ListItem item) {
    TaskParameter param = (TaskParameter) item.getModelObject();
    item.add(new Label("paramName", param.getParameterName()));
    if (param.getInputType().equals("TextField")) {
      item.add(new ParameterSpecificationPanelTF("paramSpecPanel", param));
    } else if (param.getInputType().equals("DropDownChoice")) {
      item.add(new ParameterSpecificationPanelDDC("paramSpecPanel", param));
    } else {
      item.add(new ParameterSpecificationPanelTF("paramSpecPanel", param));
    }
  }
};
form.add(parameters);

As of now, though, I have no way to actually access each ListItem in that "parameters" ListView. The problem is not with persistence, it's with getting the information from that form.
bselfridge (6) [Avatar] Offline
#7
Re: dynamic web components?
Thanks for your help Eelco. I figured out a pretty solid workaround for what I was trying to do, which I'll post here for anyone who cares to know.

For this web page one of my instance variables is now a java.util.List of TaskParameterValue objects to be persisted (this class has a built-in persist() method). In the populateItem() method of the ListView, a new TaskParameterValue is created, and the form components are initialized with a PropertyModel binding their values to the TaskParameterValue object's "value" instance variable. Then the TaskParameterValue object is added to the global list, as in: values.add(value). So then when the submit button is pressed, we simply iterate through the list (whose individual components have attributes bounded to each form component) and persist each one, as in:

for (TaskParameterValue v: values) {
  v.persist();
}

Anyway, sorry for the long-winded questions/posts. Once again, thank you for all your help!
Eelco12 (100) [Avatar] Offline
#8
Re: dynamic web components?
Yeah, something like that should work. Consider using e.g. DataView to avoid a few potential issues that ListView has. Read more about in the JavaDocs of the respective classes.