Wicket string model - java

Im still not getting the wicket models. What am I doing wrong here? filterString is still "" when the links onClick method prints it.
class X extends Panel {
String filterString;
TextField filterTextField;
AjaxLink filterLink;
X(){
filterString = new String("");
filterTextField = new TextField<String>("filterTextField", new PropertyModel<String>(this, "filterString"));
filterLink = new AjaxLink<Void>("filterLink"){
private static final long serialVersionUID = 1L;
#Override
public void onClick(AjaxRequestTarget target) {
params.setFilterString(filterTextField.getModelObject());
System.out.println("BLABLABLA " + filterTextField.getModelObject());
}
};
//add stuff etc
}
}
EDIT:
OK, like Juha said using a Form works. Sometimes I feel like creating forms feels like overkill but since this is probably the most Wicket-y thing to do anyway, it is what I will use here. The class would look something like this:
public class X extends Panel {
private static final long serialVersionUID = 1L;
public X(String id) {
super(id);
add(new FilterForm("logEntryForm"));
}
public class FilterForm extends Form{
private static final long serialVersionUID = 1L;
private transient String text; //no need to serialize this
public FilterForm(String id) {
super(id);
final TextField<String> contents = new TextField<String>("contents", new PropertyModel<String>(FilterForm.this, "text")); //textArea for user to enter the filter String
add(contents);
add(new AjaxButton("filterButton") {
private static final long serialVersionUID = 1L;
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
//do stuff, in my case it was to send the text to the database for filtering out results
}
});
}
}
}

Replace AjaxLink with Form and AjaxButton or something that has onSubmit() method. AjaxLink doesn't do submit so browser doesn't send the input value to server.

In constructor it seems you have written x() rather than X() (capital X)

Related

How to implement editable grid with 2 related dropdown in wicket?

I need to show the data from DB in table format with edit, save , cancel, delete button, its called editable grid in wicket.
In Table row after click on edit button data should be shown on 2 dropdown choices and select data from 1st dropdown then 2nd dropdown data model should be changed based on selection of first dropdown.
I have gone through the https://github.com/wicketstuff/core/tree/master/editable-grid-parent. But its showing only editable grid with 1 dropdown in wicket and i want 2 dropdown. Please help on this.
UPDATE :
I have used this
private List<AbstractEditablePropertyColumn<Person, String>> getColumns()
{
List<AbstractEditablePropertyColumn<Person, String>> columns = new ArrayList<AbstractEditablePropertyColumn<Person, String>>();
stateDropDownPropertyColumn = new AbstractEditablePropertyColumn<Person, String>(new PropertyModel<String>(this, "selectedMake"), "state")
{
private static final long serialVersionUID = 1L;
public EditableCellPanel<Person> getEditableCellPanel(String componentId)
{
return getStateDDCellpanel(componentId,this);
}
};
cityDropDownPropertyColumn = new AbstractEditablePropertyColumn<Person, String>(new Model<String>("CarModel"), "city"){
private static final long serialVersionUID = 1L;
#Override
public EditableCellPanel<Person> getEditableCellPanel(String componentId) {
// TODO Auto-generated method stub
return getCityDDCellpanel(componentId,this);
}};
columns.add(stateDropDownPropertyColumn);
columns.add(cityDropDownPropertyColumn);
return columns;
}
private EditableRequiredDropDownCellPanel<Person, String> getStateDDCellpanel(String componentId,
AbstractEditablePropertyColumn<Person, String> DropDownPropertyColumn){
this.stateComponentID = componentId;
this.stateDropDownPropertyColumn = DropDownPropertyColumn;
stateDropDownCellPanel = new EditableRequiredDropDownCellPanel<Person, String>(stateComponentID, stateDropDownPropertyColumn, stateChoices);
return stateDropDownCellPanel;
}
private EditableRequiredDropDownCellPanel<Person, String> getCityDDCellpanel(String componentId,
AbstractEditablePropertyColumn<Person, String> DropDownPropertyColumn){
this.cityComponentID = componentId;
this.cityDropDownPropertyColumn = DropDownPropertyColumn;
cityDropDownCellPanel = new EditableRequiredDropDownCellPanel<Person, String>(cityComponentID, cityDropDownPropertyColumn, cityChoices);
cityDropDownCellPanel.setOutputMarkupId(true);
cityDropDownCellPanel.setOutputMarkupPlaceholderTag(true);
return cityDropDownCellPanel;
}
I have not any idea about this where i need to put up behaviours of dropdown cell.
Probably almost direct answer to question according to dynamic list (first is fixed, second id depended, dynamically computed):
http://examples7x.wicket.apache.org/ajax/choice
To be with SO rules not to include pure links, excerpt from official example Apache licensed
(prepared to be shorter - not compile)
Model allows You prepare changed data, and AJAX event forces refresh - this is core of idea. Event (ajax behaviour) connected to first 'makers', and behaviour forces to refresh 'models' . This is typical wicket+ajax pattern.
/**
* Linked select boxes example
*
* #author Igor Vaynberg (ivaynberg)
*/
public class ChoicePage extends BasePage
{
private String selectedMake;
private final Map<String, List<String>> modelsMap = new HashMap<>(); // map:company->model
/**
* #return Currently selected make
*/
public String getSelectedMake()
{
return selectedMake;
}
/**
* #param selectedMake
* The make that is currently selected
*/
public void setSelectedMake(String selectedMake)
{
this.selectedMake = selectedMake;
}
/**
* Constructor.
*/
public ChoicePage()
{
modelsMap.put("AUDI", Arrays.asList("A4", "A6", "TT"));
modelsMap.put("CADILLAC", Arrays.asList("CTS", "DTS", "ESCALADE", "SRX", "DEVILLE"));
modelsMap.put("FORD", Arrays.asList("CROWN", "ESCAPE", "EXPEDITION", "EXPLORER", "F-150"));
IModel<List<String>> makeChoices = new AbstractReadOnlyModel<List<String>>()
{
#Override
public List<String> getObject()
{
return new ArrayList<>(modelsMap.keySet());
}
};
IModel<List<String>> modelChoices = new AbstractReadOnlyModel<List<String>>()
{
#Override
public List<String> getObject()
{
List<String> models = modelsMap.get(selectedMake);
if (models == null)
{
models = Collections.emptyList();
}
return models;
}
};
Form<?> form = new Form("form");
add(form);
final DropDownChoice<String> makes = new DropDownChoice<>("makes",
new PropertyModel<String>(this, "selectedMake"), makeChoices);
final DropDownChoice<String> models = new DropDownChoice<>("models",
new Model<String>(), modelChoices);
models.setOutputMarkupId(true);
form.add(makes);
form.add(models);
...
makes.add(new AjaxFormComponentUpdatingBehavior("change")
{
#Override
protected void onUpdate(AjaxRequestTarget target)
{
target.add(models);
}
});
}
}
UPDATE after comment. Lets back to previous github code, must replace fixed list by model. How??? Derive or copy, add contructor with IModel ... Wicket has very good object design.
In similar way we add column types not known to (not planned) grid author.
BTW Your comment 'its not working' is very broad. Sorry, I can help if I can, but dont make full project for You. Hope You will enjoy with coding.
package org.wicketstuff.egrid.column;
import java.util.List;
import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.FormComponent;
/**
*
* #author Nadeem Mohammad
*
*/
public class EditableRequiredDropDownCellPanel<T, S> extends EditableCellPanel
{
private static final long serialVersionUID = 1L;
public EditableRequiredDropDownCellPanel(final String id, final PropertyColumn<T, S> column, #SuppressWarnings("rawtypes") final List choices)
{
super(id);
#SuppressWarnings("unchecked")
DropDownChoice<T> field = new DropDownChoice<T>("dropdown", choices); <--- **** Here should be model ****
field.setLabel(column.getDisplayModel());
add(field);
}
#Override
public FormComponent<?> getEditableComponent()
{
return (FormComponent<?>) get("dropdown");
}
}
then with changed class return here:
columns.add(new AbstractEditablePropertyColumn<Person, String>(new Model<String>("Age"), "age")
{
private static final long serialVersionUID = 1L;
public EditableCellPanel getEditableCellPanel(String componentId)
{
return new ***** EditableRequiredDropDownCellPanel ***** <Person, String>(componentId, this, Arrays.asList("10","11","12","13","14","15"));
}
});
add Beahviours too

How to display different image on click of three div in wicket?

I am new to apache wicket. I need to display a default image for a div in wicket. On click of left side of image i want to replace it other image and for right side of the click i want to replace it with another image.
For this I came up with following html and java codes:
<html>
<head>
<title>Wicket Hello World</title>
<style>
#linkDecisionContainer.left{
background-image: url("Desert.jpg");
}
#linkDecisionContainer.default{
background-image: url("Koala.jpg");
}
#linkDecisionContainer.right{
background-image: url("Penguins.jpg");
}
</style>
</head>
<body>
<div wicket:id ="linkDecisionContainer">
<a wicket:id="leftChoice"></a>
<a wicket:id="defaultChoice"></a>
<a wicket:id="rightChoice"></a>
</div>
</body>
</html>
I tried to add default class to a WebMarkupContainer and on the click event i added left and right classes accordingly.
public class Hello extends WebPage {
private static final long serialVersionUID = 1L;
WebMarkupContainer ldc=new WebMarkupContainer("linkDecisionContainer");
private AjaxLink left;
private AjaxLink right;
public Hello() {
super();
ldc.add(new AttributeModifier("class", true, new Model<String>("default")));
left = new AjaxLink("leftChoice") {
private static final long serialVersionUID = 1L;
#Override
public void onClick(AjaxRequestTarget target) {
switchView("left");
target.addComponent(right);
}
};
right = new AjaxLink("rightChoice") {
private static final long serialVersionUID = 1L;
#Override
public void onClick(AjaxRequestTarget target) {
switchView("right");
target.addComponent(right);
}
};
add(left);
add(right);
}
private void switchView(String viewName) {
if (viewName.equals("left")) {
ldc.add(new AttributeModifier("class", true, new Model<String>("left")));
}
else if (viewName.equals("right")) {
ldc.add(new AttributeModifier("class", true, new Model<String>("right")));
}
}
}
Could anyone please guide me to achieve it?
From the code you provided it looks like you don't refresh the "linkDecisionContainer". Additionally you shouldn't add more and more AttributeModifier classes but instead just change the value of the underlying model. The AttributeModifier won't be replaced by adding another one. Therefore you're relying on the Implementation of Behaviors to determine which Modifier acutally wins.
private IModel<String> ldcClassModel;
public Hello() {
super();
ldcClassModel = Model.of("default");
final WebMarkupContainer ldc = new WebMarkupContainer("linkDecisionContainer");
add(ldc);
ldc.setOutputMarkupId(true);
ldc.add(new AttributeModifier("class", ldcClassModel));
AjaxLink left = new AjaxLink("leftChoice") {
private static final long serialVersionUID = 1L;
#Override
public void onClick(AjaxRequestTarget target) {
ldcClassModel.setObject("left");
target.addComponent(ldc);
}
};
AjaxLink right = new AjaxLink("rightChoice") {
private static final long serialVersionUID = 1L;
#Override
public void onClick(AjaxRequestTarget target) {
ldcClassModel.setObject("right");
target.addComponent(ldc);
}
};
add(left);
add(right);
}

Wicket : CheckBoxMultipleChoice is not saving values in model object

My code looks like this
html
< div wicket:id="metroEthernetChildchkLeft">
java code
initializing CheckBoxMultipleChoice in constructor and then later setting the values of list and model using setter methods
class <some name>
private CheckBoxMultipleChoice<String> metroEthernetChildchkLeft;
<constructor>()
{ metroEthernetChildchkLeft = new CheckBoxMultipleChoice<String>("metroEthernetChildchkLeft");
metroEthernetChildchkLeft.setMarkupId("metroEthernetChildchkLeftId");
metroEthernetChildchkLeft.add(AttributeModifier.prepend("load", "javascript:addMargin(metroEthernetChildchkLeftId);"));
metroEthernetChildchkLeft.setEnabled(false);
commentTechSpeedMetroEthernetListView.add(metroEthernetChildchkLeft);
add(new IndicatingAjaxButton("submitChoiceCmd")
{
private static final long serialVersionUID = 1L;
#Override
protected void onSubmit(AjaxRequestTarget target, Form< ? > form)
{
//// >>>>>>>> updated model value is not coming here <<<<<<
meSpeedSelectLeft = (ArrayList<String>) metaCommentTechSpeedBean.getMeSpeedSelectLeft();
});
}
method()
{
meSpeedSelectLeft = (ArrayList<String>) metaCommentTechSpeedBean.getMeSpeedSelectLeft();
leasedLineChildDivLeft.setDefaultModel(new PropertyModel(metaCommentTechSpeedBean, "llSpeedSelectLeft"));
leasedLineChildDivLeft.setChoices(llSpeedListLeft);
}
i am not able to get checked values [array list of selected checkboxes] in submit method {located in constructor}
Updated :
<div wicket:id="metroEthernetChildchkLeft"></div>
public class MetaCommentTechSpeedChoiceForm extends OForm<MetaCommentTechSpeedBean>
{
private CheckBoxMultipleChoice<String> metroEthernetChildchkLeft;
public MetaCommentTechSpeedChoiceForm(String id)
{
super(id);
metroEthernetChildchkLeft = new CheckBoxMultipleChoice<String>("metroEthernetChildchkLeft");
metroEthernetChildchkLeft.setMarkupId("metroEthernetChildchkLeftId");
metroEthernetChildchkLeft.add(AttributeModifier.prepend("load", "javascript:addMargin(metroEthernetChildchkLeftId);"));
metroEthernetChildchkLeft.setEnabled(false);
commentTechSpeedMetroEthernetListView.add(metroEthernetChildchkLeft);
add(new IndicatingAjaxButton("submitChoiceCmd")
{
private static final long serialVersionUID = 1L;
#Override
protected void onSubmit(AjaxRequestTarget target, Form< ? > form)
{
meSpeedSelectLeft = (ArrayList<String>) metaCommentTechSpeedBean.getMeSpeedSelectLeft(); //// >>>>>>>> updated model value is not coming here <<<<<<
});
}
public void formFunction(final MetaCommentCreationBean metaCommentCreationBean, final Component basicInfoContainer, final Component techSpeedSettingsContainer)
{
meSpeedSelectLeft = (ArrayList<String>) metaCommentTechSpeedBean.getMeSpeedSelectLeft();
leasedLineChildDivLeft.setDefaultModel(new PropertyModel(metaCommentTechSpeedBean, "llSpeedSelectLeft"));
leasedLineChildDivLeft.setChoices(llSpeedListLeft);
}
the problem occurred due to this line
metroEthernetChildchkLeft.setEnabled(false);
i disabled the control and enabling it on frontend using javascript.
Wicket still thinks that the control is disabled and hence not updating the model object.

Building a Reuseable Wicket Component

So this is not a very general question, but I was hoping some people could give me some pointers on architecture so that I can build the following reusable wicket component.
Here is a rough sketch on skitch:
https://skitch.com/cmagnollay/8sn2s/multitextform
I know, great drawing right? So essentially, this formcomponent (i think this is the right class to use) will be used to add a user defined number of inputs on a form. When the user hits the - button next to a TextInputField it removes that inputField. When they hit the + button, a new blank field is added. Obviously the component will need to use AJAX to update the component when the user clicks the buttons, but my issue is how to structure this. Is this one class? two (one for whole component, one for inputfield with - button), what classes should I be using to do this? I would like the object to be as general as possible to promote reuse. Here is what I have so far:
public class MultiTextInput<T> extends FormComponent<List<T>>
{
private static final long serialVersionUID = 1L;
private final String removeInputButtonName = "removeInputButton";
private final String addInputButtonIdName = "addInputButton";
private int numInputs = 1;
private List<TextField<T>> inputFieldList = new ArrayList<TextField<T>>();
public MultiTextInput(String id, IModel<T> model)
{
super(id);
inputFieldList.add(new TextField<T>("input1", model));
add(inputFieldList.get(0));
addAddInputFieldMarkup();
}
/**
* Adds an "add" button.
*/
private void addAddInputFieldMarkup()
{
Button addInputButton = new Button(this.addInputButtonIdName + numInputs);
addInputButton.add(new AjaxFormComponentUpdatingBehavior("onclick"){
private static final long serialVersionUID = 1L;
#Override
protected void onUpdate(AjaxRequestTarget target)
{
numInputs++;
inputFieldList.add(new TextField<T>("input" + numInputs));
target.add(MultiTextInput.this);
}
});
}
/**
* Adds a "remove" button.
*/
private void addRemoveInputFieldMarkup()
{
Button removeInputButton = new Button(this.removeInputButtonName + numInputs);
removeInputButton.add(new AjaxFormComponentUpdatingBehavior("onclick"){
private static final long serialVersionUID = 1L;
#Override
protected void onUpdate(AjaxRequestTarget arg0)
{
// TODO Auto-generated method stub
}
});
}
}
As I said, I am just trying to get used to thinking about making Wicket components. I have a lot of experience with OO, but just not particularly with wicket. Thanks for any help and direction!
I guess the easiest way to implement the desired behavior would be to use a ListView backed by a List. And just reload after the add/remove button has been pressed.
Here is a code scribble (not tested)
public abstract class MultiTextPanel<T> extends Panel {
public MultiTextPanel(String id, IModel<ArrayList<T>> model) {
super(id, model);
final Form<ArrayList<T>> multiTextForm = new Form<ArrayList<T>>("multiTextForm", model);
add(multiTextForm);
final ListView<T> listView = new ListView<T>("listView", model) {
#Override
protected void populateItem(final ListItem<T> item) {
// TODO Auto-generated method stub
TextField<T> textField = new TextField<T>("textField", item.getModel());
add(textField);
AjaxSubmitLink removeButton = new AjaxSubmitLink("removeButton", multiTextForm) {
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
multiTextForm.getModelObject().remove(item.getModelObject());
target.addComponent(multiTextForm);
}
#Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
//errors should be ignored, we shoudlnt validate in our form, so this shouldnt happen anyway
multiTextForm.getModelObject().remove(item.getModelObject());
target.addComponent(multiTextForm);
}
};
add(removeButton);
}
};
add(listView);
AjaxSubmitLink addButton = new AjaxSubmitLink("addButton", multiTextForm) {
#Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
//errors should be ignored, we shoudlnt validate in our form, so this shouldnt happen anyway
multiTextForm.getModelObject().add(createNewT());
target.addComponent(multiTextForm);
}
#Override
protected void onSubmit(AjaxRequestTarget target, Form form) {
multiTextForm.getModelObject().add(createNewT());
target.addComponent(multiTextForm);
}
};
add(addButton);
}
public abstract T createNewT();}
Basic html:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.sourceforge.net/" xml:lang="en" lang="en">
<wicket:panel>
<form wicket:id="multiTextForm">
<wicket:container wicket:id="listView">
<input type="text" wicket:id="textField" />
<a wicket:id="removeButton">-</a>
</wicket:container>
</form>
<a wicket:id="addButton">+</a>
</wicket:panel>
The only special thing I've done with this is to put a form around the ListView so we are able to just submit inside the Panel we've created (validation is most likely not needed at this stage and should be done in the form that saves the screen).
The downside with this implementation is that you will always reload the complete form and therefore create a lot of overhead. Only 1 row is added/removed but n(-/+)1 are re-rendered.

Implementing javascript events to Wicket

I'm new to ria-development and working with the Ajax Slider example. I can't figure out how to work with javascript events. Here in the example the onValueChanged-event is preimplemented. How do I implement say onchange- or onSlider-event?
All help greatly appreciated!
public abstract class AjaxSlider extends WebMarkupContainer {
private static final long serialVersionUID = 1L;
public AjaxSlider(String id) {
super(id);
super.setOutputMarkupId(true);
}
public JQUIComponentBehaivor<SliderOptions> getSlideBehaviors() {
List behaviors = getBehaviors();
for(Object behavior : behaviors){
if(behavior instanceof SliderBehavior)
return (SliderBehavior) behavior;
}
return null;
}
public abstract void onValueChanged(AjaxRequestTarget target,
int newValue);
#Override
protected void onInitialize() {
super.onInitialize();
AbstractDefaultAjaxBehavior ajaxBehavior =
new AbstractDefaultAjaxBehavior() {
private static final long serialVersionUID = 1L;
#Override
protected void respond(AjaxRequestTarget target) {
String sliderValue = RequestCycle.get().getRequest()
.getParameter("sv");
if (Utils.isNotBlank(sliderValue)) {
onValueChanged(target, Integer.valueOf(sliderValue));
}
}
};
super.add(ajaxBehavior);
super.add(new SliderBehavior(new SliderOptions()
.changeEvent(wicketAjaxGet(
ajaxBehavior,
new MapBuilder<String, Object>().add("sv",
js("ui.value")).build()))));
}
}
The example you gave adds an event handler for the change event. What this event handler does is issueing a GET request to the ajaxBehaviordefined above. The behavior then extracts the slider value from the GET parameters and calls onValueChanged.
You can add another event handler just like this to SliderOptions. For instance:
.slideEvent(
wicketAjaxGet(ajaxBehavior,
new MapBuilder<String, Object>()
.add("sv", js("ui.value")).build()))));
This handler should call the ajax behavior any time the user moves the slider.

Categories