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

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);
}

Related

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.

Wicket string model

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)

Struts2 select tag save and recall issue

I am getting confused trying to use the struts2 tag. I have followed several examples and they all seem to have the same usage pattern, but this doesn't work for me (below is all of the code that is relevant).
Basically, the struts2 select drop down allows me to display the initial list and save the value, but does not get displayed correctly when I bring the page up to edit the object. Once the page is displayed, all select values display the default instead of the expected value. If I modify the select value and save the page again, it will correctly save the value. Somewhere, the tag is not properly setting the SELECTED value of the option list. I am able to view the correct change being persisted to the database, so I know the action is correctly receiving the object.
I believe the problem lies somewhere within the <s:select list="lifeInsuranceStatuses" name="domainObject.lifeInsuranceCoverages[%{#status.index}].lifeInsuranceStatus.oid" listKey="oid" listValue="status" theme="simple" /> line of the JSP, but I may be wrong. It seems like all of the pieces of this page work except for setting the proper value of the drop down when the object is recalled.
Where I expect this
public class MemberAction
extends AbstractAction<Member>
{
private static final long serialVersionUID = 1L;
private Service<LifeInsuranceStatus> lifeInsuranceStatusService;
// Code removed for brevity...
public List<LifeInsuranceStatus> getLifeInsuranceStatuses()
{
return lifeInsuranceStatusService.getObjects().getResponse();
}
public Service<LifeInsuranceStatus> getLifeInsuranceStatusService()
{
return lifeInsuranceStatusService;
}
public void setLifeInsuranceStatusService(Service<LifeInsuranceStatus> lifeInsuranceStatusService)
{
this.lifeInsuranceStatusService = lifeInsuranceStatusService;
}
}
My JSP page looks like the following:
<%# page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%# taglib prefix="s" uri="/struts-tags" %>
<s:form action="saveMember" method="post">
<table border="1">
<tr>
<td>
<s:text name="domainObject.lifeInsuranceCoveragesn.lifeInsuranceStatus.status" />
</td>
</tr>
<s:div id="LifeInsuranceCoverages" theme="simple">
<s:iterator value="domainObject.lifeInsuranceCoverages" status="status">
<tr class="lifeInsuranceCoverageRow<s:property value="%{#status.index}" />">
<td>
<s:select list="lifeInsuranceStatuses" name="domainObject.lifeInsuranceCoverages[%{#status.index}].lifeInsuranceStatus.oid" listKey="oid" listValue="status" theme="simple" />
</td>
</tr>
</s:iterator>
</s:div>
<tr id="addLifeInsuranceCoverageRow">
<td>
Add Life Insurance Coverage...
</td>
</tr>
</table>
<s:submit key="submit" />
</s:form>
And my model looks like:
public class Member
extends Person
{
private static final long serialVersionUID = 1L;
private List<LifeInsuranceCoverage> lifeInsuranceCoverages;
public List<LifeInsuranceCoverage> getLifeInsuranceCoverages()
{
if (lifeInsuranceCoverages == null)
{
lifeInsuranceCoverages = new ArrayList<LifeInsuranceCoverage>();
}
return lifeInsuranceCoverages;
}
public LifeInsuranceCoverage getActiveLifeInsuranceCoverage()
{
if (lifeInsuranceCoverages == null || lifeInsuranceCoverages.size() < 1)
{
return null;
}
else
{
return lifeInsuranceCoverages.get(lifeInsuranceCoverages.size() - 1);
}
}
public void setLifeInsuranceCoverages(List<LifeInsuranceCoverage> lifeInsuranceCoverages)
{
this.lifeInsuranceCoverages = lifeInsuranceCoverages;
for (LifeInsuranceCoverage lifeInsuranceCoverage : this.lifeInsuranceCoverages)
{
lifeInsuranceCoverage.setMember(this);
}
}
public void addLifeInsuranceCoverage(LifeInsuranceCoverage lifeInsuranceCoverage)
{
lifeInsuranceCoverage.setMember(this);
getLifeInsuranceCoverages().add(lifeInsuranceCoverage);
}
public void removeLifeInsuranceCoverage(LifeInsuranceCoverage lifeInsuranceCoverage)
{
getLifeInsuranceCoverages().remove(lifeInsuranceCoverage);
lifeInsuranceCoverage.setMember(null);
}
}
... and ...
public class LifeInsuranceCoverage
extends AbstractDomainObject
{
private static final long serialVersionUID = 1L;
private Member member;
private LifeInsuranceStatus lifeInsuranceStatus;
public LifeInsuranceStatus getLifeInsuranceStatus()
{
return lifeInsuranceStatus;
}
public void setLifeInsuranceStatus(LifeInsuranceStatus lifeInsuranceStatus)
{
this.lifeInsuranceStatus = lifeInsuranceStatus;
}
public Member getMember()
{
return member;
}
public void setMember(Member member)
{
this.member = member;
}
}
... and ...
public class LifeInsuranceStatus
extends AbstractDomainObject
{
private static final long serialVersionUID = 1L;
private String status;
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
}
... and also ...
public abstract class AbstractDomainObject
implements DomainObject
{
private static final long serialVersionUID = 1L;
private Long oid;
public Long getOid()
{
return oid;
}
public void setOid(Long oid)
{
this.oid = oid;
}
}
I was able to figure out this issue after some trial and error. The solution I found doesn't make sense to me but it works regardless.
In order to fix this, I had to do two things. First, I added a toString() method in the LifeInsuranceStatus class that returned just the status value. Then I removed the listKey portion of the struts2 tag. Once I did these two things together, the value I stored in the database was recalled properly and saved properly.
I would love to know why this worked this way. Anyone have better knowledge of struts2 tags or why another drop down that used an enum worked perfectly fine without removing the listKey portion of the tag...

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