Models not updating on initial load of homepage in Wicket - java

I'm having some problems understanding what I'm doing wrong.
What I do:
Override getHomePage() in my Application. I return MyStartPage.class.
MyStartPage is a subclass of MySubPage.
MySubPage is a subclass of MySuperPage.
In MySuperPage I add a Panel. This Panel has a TextField and WebMarkupContainer with a AjaxEventBehavior(onclick) that prints the backing modelObject of the textfield.
What happens when I start my server and browse localhost/MyApp:
The printed modelObject is null even though the user input is not when I click my WebMarkupContainer.
What happens when I start my server, browse localhost/MyApp, go to another Page in my app and then back to MyStartPage:
The printed modelObject matches the user input when I click my WebMarkupContainer.
It also works when I do the following:
Override getHomePage() in my Application and return MyLoginPage. MyLoginPage contains MySigninPanel. In MySigninPanel I override onSignInSucceeded() like this:
#Override
protected void onSignInSucceeded() {
setResponsePage(new MyStartPage());
}
Can someone shed some light on what the correct way of getting my TextField to work properly when the user clicks the WebMarkupContainer the first thing they do?
Thanks in advance!
//EDIT :
This only seems to be a problem in Firefox, or at least it's working fine in Chrome IE9 and IE8-mode in IE9.

Your TextField's model will not be updated with user entered data unless you submit a Form with your click event. Your TextField should be the child of that Form. If it is, then it's content will be sent to the server, converted to the target type, and validated. On success, you'll be able to query the model and view the data entered on your page.
In order to do this, you should use a AjaxFormSubmitBehavior instead of the AjaxEventBehavior you are currently using:
webMarkupContainer.add(new AjaxFormSubmitBehavior(form, "onclick") {
#Override
protected void onSubmit(AjaxRequestTarget target) {
// You can now see what was entered in your TextField
System.out.println(textField.getModelObject());
}
#Override
protected void onError(AjaxRequestTarget target) {
// An error occurred and you should provide some kind of feedback
}
});

Well, i have a solution, although I'm not sure why it works. I added
mountPage("invoice/overview", OverviewPage.class);
In my WebApplication, and now it works in FireFox (OverviewPage is referred to as 'MyStartPage' in my initial post).
Here is what the wicket.ajax.baseurl and the typed url in the browser looked like before the change, when it did not work:
baseUrl: wicket/bookmarkable/eyesys.web.invoice.overview.OverviewPage
browser url: wicket/bookmarkable/eyesys.web.invoice.overview.OverviewPage?1
And after the change:
baseUrl: invoice/overview
browser url: invoice/overview?1

Related

Wicket quick double click submit button

I have a problem with a Wicket Form. In my form if a User click twice quickly on a SubmitLink the onSubmit method called twice and there where 2 instances of an object. How can I prevent this? I have tried using a boolean variable
#Override
public void onSubmit(){
if(!submitted){
submitted = true;
dao.save(object);
setResponsePage(differentPage.class);
}
}
This method doesn't work for me. Can anyone help me please?
There are some work around To prevent double submit.
I guess you may not added renderStrategy.So first add setRenderStrategy in Your application class .
Direct, IRequestCycleSettings.RenderStrategy.ONE_PASS_RENDER. Everything is handled in one physical request. This is efficient, and is the best option if you want to do sophisticated clustering. It does not however, shield you from what is commonly known as the Double submit problem.
getRequestCycleSettings().setRenderStrategy(RequestCycleSettings.RenderStrategy.ONE_PASS_RENDER);
Probably above solution will work with your case. On top of that
You can disable the button on click submit or You can use some indicatorbutton link .
I resolve with this lines of code
save_btn = new AjaxSubmitLink("submit_btn", this) {
protected void onSubmit(AjaxRequestTarget art){
art.appendJavaScript("e.preventDefault();");
}
};
And the
getRequestCycleSettings().setRenderStrategy(RequestCycleSettings.RenderStrategy.ONE_PASS_RENDER);
of course

Combobox doesn't react to ".setValue()" nor ".select()"

This is my code:
comboBoxInstance.setInputPrompt("Something...");
comboBoxInstance.setNullSelectionAllowed(false);
Cookie comboCookie = getCookieByName("combo");
comboBoxInstance.select((comboCookie != null) ? comboCookie.getValue() : null);
final TextField textFieldInstance = new TextField("Textfield");
textFieldInstance.setInputPrompt("Something...");
Cookie tfCookie = getCookieByName("tf");
textFieldInstance.setValue((tfCookie != null) ? tfCookie.getValue() : null);
The problem is that the textfield works pretty well with the "Cookie setup". Only the combobox is refusing to work like it should.
The output is like this:
I've tried to use .setValue() instead of .select() but this has pretty much the same effect. I've also made sure that both the Cookie itself and the correct value are provided.
It may help to have a look at the part where the cookie is generated:
Cookie comboCookie = new Cookie("combo", comboBoxInstance.getValue().toString());
cookieProcessing(costcentreCookie); //<- sets maxage and vaadin related stuff (like adding the cookie)
Edit:
A few points to the data flow.
I'm generating a ComboBox with a SimpleJDBCConnectionPool's SQLContainer as the data container (coming from a TableQuery). Here's the initialization (executed in the constructor) in the combobox class:
private void init() throws SQLException {
this.setContainerDataSource(generateContainer());
this.setItemCaptionPropertyId("something");
}
The private method generateContainer() returns the SQLContainer of course.
This happens if I click on a particular button which opens up a dialog. This dialog is the fragment shown in the picture above. The combobox - of course - is part of it.
What one is supposed to do now is setting his data (get an item of the ComboBox) and hit save. The save button executes the routine to store the cookies. It's the code already mentioned above (Cookie comboCookie = new Cookie(...).
Okay, now the user is going to open up the dialog again. It's not important whether he reloads the application or just reopens the dialog (or does something else). It's basically the same in the app.
The dialog opens up and initializes the combobox (and the textfield) once again. However, this time it's supposed to gather the data out of the stored cookies. This is were the issue happens. This works well for the textfields (there are two but I've omitted one for shortening reasons) but not for the combobox, even tough it should've the exact same data as before. Hold in mind that it's the exact same class with the exact same initialization as when we stored the cookies in the first place.
I've the vague presumption, that it has to do something how the code is stacked. Maybe it hasn't finished loading the datacontainer while trying to set the appropriated value which then can't be found.
Edit2:
I've finally managed to reveal something. The ComboBox is indeed empty when the ".select()" is executed. However, this means, that the ComboBox is left untouched (it's only kind of "linked" to the datacontainer) until someone drops down the items. As soon as this happens, the items are there and I can possibly select them.
Is it supposed to work like this? O.o Am I able to fully initialize the combobox before I do something else? Something like:
private void init() throws SQLException {
this.setContainerDataSource(generateContainer());
this.setItemCaptionPropertyId("something");
this.gatherTheItems();
}
Edit3 - Test with ".setImmediate(true)"
I've changed the init to:
private void init() throws SQLException {
this.setContainerDataSource(generateContainer());
this.setItemCaptionPropertyId("SOMETHING");
this.setImmediate(true);
}
This didn't change anything. The combobox is still empty:
Finally! At first I've found a workaround which was like this:
for (Iterator it_IDS = combobox.getItemIds().iterator(); it_IDS.hasNext();) {
Object id = (Object) it_IDS.next();
if(id.toString().equals(cookie.getValue().toString())){
combo2.select(id);
break;
}
}
However, I couldn't believe that this was working since it doesn't change anything at the core problem. So I've investigated, that the RowID is built via a BigDecimal and voilà:
if(cookie != null) {
combobox.select(new RowId(new BigDecimal(cookie.getValue())));
}
I'm so happy right now :) Thanks for your patience kukis.
In case you came here because you're experiencing the same issue using a BeanItemContainer as datasource, bear in mind that you must implement both equals()and hashCode() methods on the underlying class for ComboBox's select() or setValue() methods to work.
You have plenty examples on Vaadin Forum on how to implement these methods:
ComboBox select value problem
Select or ComboBox does not Show Selected Property
Combobox select/setValue

Apache wicket: how to update form explicitly?

I have an issue with ListView and validation on page.
I have ListView, and underneath it I have TextField, where the user can enter values. I have "publish" and "draft save" buttons on my page. Publish is a button, where popup (ModalWindow) is shown, where user should confirm entered data. Save draft is saving without confirmation. Both are SecuredAjaxLink objects.
When a user enters data in TextField, it is saved in ListView, but the whole list isn't updated as user should press button Add below. This is ok.
The problem is, that I have business validation, where user entered information is checked for some rules. When validation failing all fields (containing wrong info) are highlighted with css. To explicitly add value from TextField to ListView i'm doing
target.addComponent(form);
This is performed before data goes to validation. So all fields are updated. This works fine for publish button (with confirmation ModalWindow), but doesn't work with the link without popup. As I understand there is something wrong with lifecycle of target, but I'm stuck with it.
Maybe someone had something similar or know the answer?
How can I update the page without using popup?
Here is the code:
Draft link:
add(new SecuredAjaxSubmitLink(LinkNames.savelaterLink.toString(), form,
RoleController.CONTROLLER.getAccessController()) {
#Override
public void onSubmit(AjaxRequestTarget target, Form form) {
target.addComponent(form);
insert(appl, false, form, target, new MainMenu(getString("accept.application.draft.success.message")), trail, checkbox);
}
Publish link:
add(new CustomAjaxSubmitLink(LinkNames.submitLink.toString(), form,
RoleController.CONTROLLER.getAccessController()) {
#Override
protected void onSubmit(AjaxRequestTarget target, Form form) {
target.addComponent(form);
publishPopup.show(target);
}
});
publishPopup.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {
public void onClose(AjaxRequestTarget target) {
if (ApplicationInsertActionPanel.this.getSelectedAction() != null
&& ApplicationInsertActionPanel.this.getSelectedAction().equals(Action.CONFIRM)) {
insert(appl,
true,
form,
target,
new MainMenu(ApplicationInsertActionPanel.this
.getString("accept.application.publish.success.message")), trail, checkbox);
}
}
});
I've added
#Override
protected void onError(final AjaxRequestTarget target, Form<?> form)
{
super.onError(target, form);
target.addComponent(form);
to my draft link, but still page is not fully updated.
I suppose it is because target's lifecycle is not ended, like it is ending when i'm using popup window. Popup window is opening "new page" and old target can be updated, but when i'm not using popup, the page stays like it was.
So now i'm thinking about some workaround to end target lifecycle. I was thinking about transparent popup window without any functionality, but is really very dirty solution.
Any ideas? Thanks!
}
My english isnt so well, and i dont totally understand you Post.
is it:
type word in Textfield --> one of those submit buttons
--> word appears on listview?
if you want to Validate the input why dont you use a class that inherits from IValidator.class
and if you want to update your form you can add a updatebehaviour to your form
final AjaxFormSubmitBehavior formbehavior = new AjaxFormSubmitBehavior("onChange") {
#Override
protected void onError(AjaxRequestTarget arg0) {
arg0.add(getForm());
}
#Override
protected void onSubmit(AjaxRequestTarget arg0) {
arg0.add(getForm());
}
};
then you can add this behaviour to your form or extend it to your needs
form.add(formbehavior)
i dont know if your problem is somehow related to my answer, but i suppose that you wanted to know how to update your form without loading the page new.

Wrapping/decorating GWT FileUpload

GWT FileUpload comes as a widget that produces so that one can upload a file during form submit (at least it's how I understand it :) ) What I want to do is to make it a better-looking and get rid of standard "Browse..." button.
Since I don't have good GWT experience (and no JavaScript), I looked for existing solutions and found quite a good project - gwtupload. It's good, but I realized I'd love to have my own miniature version (and also, I was curious about how it works). So I browsed through code and tried to extract the magic part. I realized that GWT FileInput is used, but it's not shown, and Button clicks are delegated to this FileInput. The code I tried to extract (only the part that delegates the click) after reviewing sources of gwtupload contains this tricky elem.click() JSNI:
class MyUpload extends Composite {
private static native void clickOnInputFile(Element elem) /*-{
elem.click();
}-*/;
public MyUpload() {
final FileUpload upload = new FileUpload();
AbsolutePanel container = new AbsolutePanel();
// container.add(upload);
Button btn = new Button("My Browse..");
btn.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
clickOnInputFile(upload.getElement());
}
});
container.add(btn);
initWidget(container);
}
}
But this seems not to work: clicking on 'My Browse..' results in no effect (just in case I also tried running with un-commented container.add(upload) line) . Could you please help me in understanding what's wrong/missing in this code sample?
Thank you in advance.
P.S. I know that I have to place it on the FormPanel, and I know the rest about how to perform the actual submit/handling in Servlet; the only thing I want to do is this kind of decoration.
Since I have not received any answers, I had to have more investigation of this issue, so I performed a deeper code analysis of gwtupload project in order to understand how GWT FileUpload (which gets transformed into ) can be decorated.
It turned out that element.click() will only work in browsers which support #click() method (IE, Chrome, Safari). Actually, Manuel Carrasco Moñino - project author - mentions it within comments. There's second approach (for Firefox & Opera) that uses hack when FileInput is placed on transparent panel, which however is placed over some decorated button (using absolute positioning); comment by Manuel:
When the user puts his mouse over the button and clicks on it, what really happens is that the user clicks on the transparent file input showing the choose file dialog.
After that, the main work is correctly applying style attributes to elements.
Thus, there are two implementations of custom file upload component, and GWT deferred binding is used to instantiate them depending on Browser.
As for example I mention in my question, there're few fixes ("upload" has to be added to to the container, and it can be set to #setVisible(false)):
class MyUpload extends Composite {
private static native void clickOnInputFile(Element elem) /*-{
elem.click();
}-*/;
public MyUpload() {
final FileUploadWithMouseEvents upload = new FileUploadWithMouseEvents();
AbsolutePanel container = new AbsolutePanel();
container.add(upload);
upload.setVisible(false);
Button btn = new Button("My Browse..");
btn.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
clickOnInputFile(upload.getElement());
}
});
container.add(btn);
initWidget(container);
}
}
This example works fine in IE8.
P.S. Thanks to Manuel for his great library :)

Wicket: reload AjaxLazyLoadPanel automatically

I have a page with a form. Using the data from the form I get information from a BBDD and I displayed in a panel using Ajax.
Now I was trying to use a AjaxLazyLoadPanel, because some of the query in the BBDD are heavy. The problem i have is after the first load of AjaxLazyLoadPanel, i dont know how to reload it with the new content (a new search).
Any advice??
Thanks!!
I have not worked with AjaxLazyLoadPanel, but the generic approach to periodically updating a component is attaching an AjaxSelfUpdatingTimerBehavior:
add(new AjaxLazyLoadPanel("myPanel"){
// implementation here
}
.setOutputMarkupId()
.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(2))));
Or, if that does not work, at the behavior to a different component and let the AjaxRequestTarget add the AjaxLazyLoadPanel (you might have to attach the AjaxLazyLoadPanel first).
Here are a few relevant links about wicket and AJAX:
How to do things in Wicket - AJAX
How Wicket does AJAX
WicketByExample.com / AJAX
How to use AjaxLazyLoadPanel in Wicket
It's not a problem with Ajax, it's about the image (the little wheel indicating "loading") that shows the first time the AjaxLazyLoadPanel is loaded.
I think I've found a solution:
Add the AjaxLazyLoadPanel in a WebMarkupContainer and in the ajax button that refreshes the content:
// lazy is the WebMarkupContainer
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
lazy.replace(new AjaxLazyLoadPanel("lazyLoadSearch") {
#Override
public Component getLazyLoadComponent(String id) {
return new SearchPanel(id, rep, searchString, typeOfSearch);
}
});
if (target != null) {
target.addComponent(lazy);
}
}

Categories

Resources