I'm a noob to Wicket and trying to change the text of a AjaxButton on submit. So the idea is that the for the first time the page loads, the user sees an AjaxButton labeled e.g. "1", after clicking the button, the label of the button changes to "2" and after the next click to "3" and so on...This can't be hard, but as I said, I'm a noobie when it comes to wicket. All help appreciated!
form.add(new AjaxButton("ajax-button", form)
{
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form)
{ //how to change Button label here?
}
}
The answer is simple: use a model.
//counter field declared in page class
private int counter;
...
form.add(new AjaxButton("ajax-button", new PropertyModel<String>(this,
"counter", form)) {
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
counter++;
target.addComponent(this);
}
});
This is probably the most important rule of Wicket: when you need something changing, use a model. This takes some time getting used to, especially if you have experience with more "traditional" frameworks, and haven't used Swing either.
N.b.: keeping the counter in your page class may not be a good idea, but the general idea is the same.
Additionally to biziclop's answer, here is a solution for text with changing parameter.
In your java code:
AjaxButton yourButton = new AjaxButton("btnId"){
//your button's implementation goes here
};
int yourVariable = 42;
Label yourLabel = new Label("labelId", new Model<String>() {
public String getObject() {
String text = MessageFormat.format(new Localizer().getString("IdForLocalizerInYourLocalizerFile", null), yourVariable);
return text;
}
})
yourButton.add(yourLabel);
In your html:
<a type="submit" wicket:id="btnId">
<span wicket:id="labelId">[This text will never be seen, will be replaced by "The var..."]</span>
</a>
Finally your localization file will contain a line like:
IdForLocalizerInYourLocalizerFile= The variable's value is {0}. It will be replaced whenever it changes and button component is added to target. Text will remain.
Related
I have a function in GWT code as below :
The table is populated dynamically, and I want to focus on the particular n'th row as per the input value.
private void focusOnRow(int pos)
{
final TextBox txtIntPaid = (TextBox) display.getDataTable2().getFlexTable().getWidget(pos,4);
System.out.println("Data"+txtIntPaid.getText()); \\ Data
System.out.println("Table:"+ display.getDataTable().getFlexTable().getWidget(pos,4)); \\ prints HTML
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute()
{
txtIntPaid.setFocus(true);
}
});
}
Here I'm able to print the data from getText(), as well as the HTML of the created widget, but I'm unable to focus on the TextBox specifically. What am I missing here ?
So I am experiencing some odd behaviour using Vaadin 7 and the ComboBox component. Essentially, what is happening is that when it first renders the form, it appears to neither have selected the null selection nor any of the items added.
I have attempted to recreate this behaviour with the following code and this demonstrates the issue.
#Override
protected void init(VaadinRequest request) {
final FieldGroup binder;
FormLayout form = new FormLayout();
form.setMargin(true);
setSizeFull();
setContent(form);
final Label output = new Label();
form.addComponent(output);
ComboBox box = new ComboBox("My Dropdown");
final PropertysetItem fields = new PropertysetItem();
fields.addItemProperty("country", new ObjectProperty<String>(""));
binder = new FieldGroup(fields);
binder.bind(box, "country");
box.addItem("aus");
box.setItemCaption("aus", "Australia");
box.addItem("uk");
box.setItemCaption("uk", "United Kingdom");
box.setRequired(true);
box.setImmediate(true);
box.setRequiredError("Country is required field");
Button submit = new Button("Submit", new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
try {
binder.commit();
output.setValue((String) fields.getItemProperty("country").getValue());
}
catch (CommitException e) {
Notification.show("fail!");
}
}
});
form.addComponent(box);
form.addComponent(submit);
}
By default the ComboBox has allow null selection set to true. So there is a blank entry, which represents a null value selection. However the ComboBox's value when first rendered neither represents the null selection nor one of the items but an empty string.
So when I load the form and click the button the outcome is neither a failure, which it should be because I haven't selected anything yet, nor one of my selections.
This is causing an issue for me in a more advanced UI application but very much the same thing going on here.
Could anybody enlighten me as to what is happening here?
Many thanks,
Joe
So when I load the form and click the button the outcome is neither a
failure, which it should be because I haven't selected anything yet,
nor one of my selections.
Combobox is not empty as you think. It has default property value, that you set as empty string:
fields.addItemProperty("country", new ObjectProperty<String>(""));
Thus form pass validation, because empty string is also a value and empty string != null.
Change this row:
fields.addItemProperty("country", new ObjectProperty<String>(""));
to:
fields.addItemProperty("country", new ObjectProperty<String>(null, String.class));
box.setNullRepresentation("-- Select Country --");
Is it possible to nest forms in Wicket that are independent of each other? I want to have a form with a submit button and a cancel button. Both buttons should direct the user to the same page (let's call it Foo). The submit button should send some info to the server first; the cancel button should do nothing.
Here's a really simplified version of my existing code:
Form form = new Form() {
public void onSubmit()
{
PageParameters params = new PageParameters();
params.put("DocumentID", docID);
setResponsePage(Foo.class, params);
}
};
DropDownChoice<String> ddc = new DropDownChoice<String>("name", new PropertyModel<String>(this, "nameSelection"), names);
ddc.setRequired(true);
final Button submitButton = new Button("Submit") {
public void onSubmit() { doSubmitStuff(true); }
};
final Button cancelButton = new Button("Cancel") {
public void onSubmit() { doSubmitStuff(false); }
};
form.add(ddc);
form.add(submitButton);
form.add(cancelButton);
form.add(new FeedbackPanel("validationMessages"));
The problem is, I just added a validator, and it fires even if I press the cancel button, since the cancel button is attached to the same form as everything else. This could be avoided if the cancel button were in a separate form. As far as I know, I can't create a separate form because — due to the structure of the HTML — the separate form would be under the existing form in the component hierarchy.
Can I make the forms separate somehow in spite of the hierarchy? Or is there some other solution I can use?
EDIT:
In response to Don Roby's comment, this is a bit closer to what my code looked like back when I was trying setDefaultFormProcessing():
Form<Object> theForm = new Form<Object>("theForm") {
public void onSubmit()
{
PageParameters params = new PageParameters();
params.put("DocumentID", docID);
setResponsePage(Foo.class, params);
}
};
final CheckBox checkbox = new CheckBox("checkbox", new PropertyModel<Boolean>(this, "something"));
checkbox.add(new PermissionsValidator());
theForm.add(checkbox);
final Button saveButton = new Button("Save") {
public void onSubmit()
{ someMethod(true); }
};
final Button cancelButton = new Button("Cancel") {
public void onSubmit()
{ someMethod(false); }
};
cancelButton.setDefaultFormProcessing(false);
theForm.add(saveButton);
theForm.add(cancelButton);
theForm.add(new FeedbackPanel("validationMessages"));
There is an even simpler solution: call the setDefaultFormProcessing method on the cancel button with false as a parameter:
cancelButton.setDefaultFormProcessing(false);
This way, clicking the cancel button will bypass the form validation (and model updating), directly calling the onSubmit function.
It is possible to "nest" forms in wicket.
See this wiki entry
for some notes on how it works and this wiki entry for how it interacts with validation.
But for what you're after, the answer from Jawher should have worked and is much simpler.
Look at this example code for hints on getting that working.
I'm wondering if you've simplified your code too far in this posting. Can you produce a sample small enough to post that definitely has the problem?
I have a Page with a Wizard component. The user can navigate the panels of the wizard by using the next and previous buttons which I have performing full (non-ajax) form submissions so that the app is back-button friendly.
When the next button is clicked, I would like to attempt ajax form validation (if javascript is enabled). I tried doing:
nextButton.add( new AjaxFormValidatingBehavior( form, "onsubmit") );
to add such validation. The behaviour works - however, when validation errors occur the browser still submits the entire form.
What is the Wicket way to prevent the browser from submitting the form in this case?
Override the onError() method on either the form or the AjaxFormValidatingBehavior. If you do it on the behavior, I am not sure if that will prevent the form from submitting or not.
new AjaxFormValidatingBehavior( form, "onsubmit") {
public void onSubmit() {}
public void onError() {}
}
Maybe a bit to late but here is the answer:
public class SomePage extends WebPage {
private FeedbackPanel feedbackMessageError = new FeedbackPanel("feedbackTabAddEmpMesError", new ExactLevelFeedbackMessageFilter(FeedbackMessage.ERROR));
public SomePage(String id) {
final Form<Void> form = new Form<>("tabFormAddEmp");
add(form);
//Name textfield cannot be empty
final FormComponent<String> tabAddEmpName = new RequiredTextField<>("tabAddEmpName", Model.of(""));
tabAddEmpName.setLabel(Model.of("Name"));
tabAddEmpName.setOutputMarkupId(true);
//Salarynumber has to be minimal 10 char long
final FormComponent<String> tabAddEmpLoon = new RequiredTextField<>("tabAddEmpLoon", Model.of(""));
tabAddEmpLoon.add(new StringValidator(10, null)).setLabel(Model.of("Salarynumber"));
tabAddEmpLoon.setOutputMarkupId(true);
final Button button = new Button("tabFormAddEmpBut");
form.add(tabAddEmpName , tabAddEmpLoon, button);
button.add(new AjaxFormValidatingBehavior(form, "onclick") {
#Override
public void onError(AjaxRequestTarget target) {
//Add feedbackpanel to your html and voila!
target.add(feedbackMessageError);
}
#Override
protected void onSubmit(AjaxRequestTarget target) {
//Do some logic over here
}
}
}
}
I have 2 inputs. When I press a button(AjaxFallbackButton), those inputs are saved into database.
If one of the input is greater than 10, when I press the button, I want to show a modal panel, for asking the user if is the sure about his option. But the modal component is not appearing. Any thoughts?
#Override
public void onSubmit(AjaxRequestTarget target) {
if (input < 10) { //save to database
} else {
AskingDialogPanel panel = new AskingDialogPanel("content",
new ResourceModel("asking.title"),
new ResourceModel("asking.message")) {
#Override
public void onOkClick(AjaxRequestTarget target) {
super.onOkClick(target);
//save to database
modalWindow.close(target);
}
#Override
public void onCancelClick(AjaxRequestTarget target) {
super.onCancelClick(target);
modalWindow.close(target);
}
};
panel.setOutputMarkupId(true);
target.addComponent(panel);
modalWindow.setContent(panel);
modalWindow.show(target);
}
Have a look at the documentation for the AjaxRequestTarget.
A component whose markup needs to be
updated should be added to this target
via
AjaxRequestTarget#addComponent(Component)
method. Its body will be rendered and
added to the envelope when the target
is processed, and refreshed on the
client side when the ajax response is
received.
I'm not sure if I remember this correctly (I've had trouble implementing the correct refresh behavior previously), but I believe you could only addComponent components that were previously added to the page, but not rendered / invisible. These will than be updated and/or their visibility re-evaluated.
I could be wrong however.. Does the above work if you substitute a normal Label for the AskingDialogPanel? (Just to verify I'm talking out the wrong end ;))