Wicket - loading data into table after page is rendered - java

In my wicket application I have a datatable. A dataprovider is attached to it and loads the content from a REST-Service. This call needs a lot of time (~ 20 seconds).
So, is there a way to load the page with an empty table and then refilling it after being rendered with data from the Service?
I thought about reattaching or reloading the dataprovider after the page is rendered:
onAfterRender()
But I still don't know how to do that with a dataprovider.

You could take a look at the AjaxLazyLoadPanel which shows a little loading icon as placeholder while the Component is loaded.
add(new AjaxLazyLoadPanel("table") {
#Override
public Component getLazyLoadComponent(String markupId) {
return new MyLongLoadingTable(markupId);
}
});
Another solution: show the empty table and periodically check for the database operation to complete and update the table when all data gathering has been done. The AbstractAjaxTimerBehavior is a good utility. Like this:
add(new AbstractAjaxTimerBehavior(Duration.ONE_SECOND) {
#Override
protected void onTimer(AjaxRequestTarget target) {
if (isDataLoaded()) {
stop(target);
target.add(table);
}
}
});

Related

GWT loading elements dynamically on page load

I have some page that should have dynamic count of check boxes, and inputs depends on data received from database
now I do like this:
make rpc call on component load (getting data for inputs)
onSuccess add inputs dynamically on the form
result: form displayed without content(because it makes call async), only after resizing, it displays content properly
(probably I can fire resize event or redraw with my self, don't know how.. )
question: I am new in GWT, What is the best way to do this task? (Now i am using gwt-ext http://gwt-ext.com/, but I think it's no matter )
update: to refresh panel it's possible to call doLayout();
I'm not familiar with gwt-ext but in "vanilla" gwt you have two options:
Refresh your widget (that should show the result) in the onSuccess method
Proceed with the rest of your code not until the result returned.
To get a bit more precise i would need more of your code.
I had a similar challenge, the content of my widget was loading for a few seconds. I display a ""Loading, please wait ..."" label until the widget is loaded:
final VerticalPanel mainPanel = new VerticalPanel();
initWidget(mainPanel);
mainPanel.add(new Label("Loading, please wait ..."));
mainPanel.add(new myCustomWidget()); // this constructor uses RPC to get content
Timer t = new Timer()
{
public void run()
{
if (!mainPanel.getWidget(1).isVisible()) {
// do nothing
} else {
// remove label "Loading, please wait ..."
mainPanel.remove(0);
// stop timer
cancel();
}
}
};
// repeat every 30 miliseconds until myCustomWidget is visible
t.scheduleRepeating(30);

Models not updating on initial load of homepage in Wicket

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

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.

Wicket panels need page refresh for javascript script to work

I am creating a web page with several tabs. To implement that I am using wicket AjaxTabbedPanel and several AbstractTab. In each tab I have tables with data and I am using a javascript script to make the tables sortable.
public TabbedPage() {
List<ITab> tabs = new ArrayList<ITab>();
tabs.add(new AbstractTab(new Model<String>("first tab")) {
public Panel getPanel(String panelId) {
return new TablePanel(panelId);
}
});
tabs.add(new AbstractTab(new Model<String>("second tab")) {
public Panel getPanel(String panelId) {
return new TablePanel(panelId);
}
});
add(new AjaxTabbedPanel("tabs", tabs));
}
When I load the page the table in the tab selected by default is sortable. However, as soon as I click any of the links to jump to other tabs (including the one of the tab already selected), none of the tables in any of the tabs allows me sort them (including the one that was previously working - the table in the default tab). If I refresh the page I can sort the table (of the tab selected in the moment of the refresh), but as soon as I click in any of links to switch tabs, the tables stop having the sortable capability again. Any ideas of why is this happening?
EDIT:
I just found that if I replace the AjaxTabbedPanel by TabbedPanel I don't have this problem. Although I'm still not sure why is that. Can anyone enlighten me?
add(new TabbedPanel("tabs", tabs));
Sorting the table by JavaScript is most likely a function called with a specific DOM-Id and seems to be executed 'onLoad'. it then accesses the currently displayed table and does it's work.
Changing the content of your Panel by Ajax doesn't trigger 'onLoad' so the function isn't executed again. TabbedPanel reloads the page and therefore executed your script.
Selecting a previous sortable table with AjaxTabbedPanel doesn't work because of the dynamically generated DOM-Ids.
Your solution is to add a AjaxCallDecorator to the links from AjaxTabbedPanel or to include the script or at least the function call to your tabbed panels.
At least this it what comes to mind without seeing any sources...
EDIT:
You might want to look at The Wicket Wiki. There's a description on how to call js after clicking an AjaxLink. That's exactly what should solve your problem.
Summary: Just add
link.add(new AttributeAppender("onclick", new Model("myTableSortingScript();"), ";"));
to the links generated by AjaxTabbedPanel.
In Wicket 6.0 you can run JavaScript on a component basis: Just override renderHead(IHeaderResponse response) for your component:
#Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
response.render(new OnLoadHeaderItem("initalizeMe(\"" + getMarkupId() + "\");"));
}
initializeMe(mycomponentId) is executed every time the component is loaded by the AjaxTabbedPanel. This also works with the standard TabbedPanel.
No real idea since I'm not sure what the code is doing but I had a similar problem with my Panel Manager. Basically if you dynamically load HTML into a panel (a div or another element) using "innerhtml" script in the content will not be executed.
To get around this I scan the loaded content for "script" tags and append them using the DOM methods - this does run the script and makes it available. My "load" method is:
// Load Content
Panel.load = function(Content) {
// "null" the old (to clear it)
Panel.innerHTML = null;
// Load the content
Panel.innerHTML = Content;
// Load Scripts
var AllScripts = Panel.getElementsByTagName("script");
var AllScriptsCnt = AllScripts.length;
for (var Cnt = 0; Cnt < AllScriptsCnt; Cnt++){
var CurScript = document.createElement('script');
CurScript.type = "text/javascript";
CurScript.text = AllScripts[Cnt].text;
Panel.appendChild(CurScript);
};
};
Again, not sure if this is the issue, but it sounds pretty much on target from my experience.

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