I have a form in Wicket with several DropDownChoice components. For one of these DropDownChoice components, I would like to keep it disabled at first and then enable it and populate it with the output of a Java function that takes as input the value of another DropDownChoice component. How would I do that with Ajax?
Take a look at org.apache.wicket.examples.ajax.builtin.ChoicePage, it does exactly what you're looking for.
First, to ajaxify the drop down choices, you need to add AjaxaFormComponentUpdatingBehaviour("onchange").
Then if you need to populate the choice list of one drop down, in other drop down's selection change, then you need to write it in the AjaxFormComponentUpdatingBehaviour("onchange") {} method.
Inside the method, you need to build the list and add it to the other drop down by setChoices(list);
As all these are done in ajax, you need to add the drop down to the ajax target by target.addComponent(doprdown2);
As the component is going to be operated in ajax you need to do the following to the second drop down
dropdown2.setOutputMarkupPlaceholderTag(true);
Full Example:
DropdownChoice ddc1 = new ("id1", model1, list1);
DropdownChoice ddc2 = new ("id2", model2, list2);
ddc2.setOutputMarkupPlaceholderTag(tag);
ddc1.add(new AjaxFormComponentUpdatingBehaviour("onchange"){
protected void onUpdate(AjaxRequestTarget target) {
// Build the list2
ddc2.setChoices(list2);
target.addComponent(ddc2);
}
});
Related
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
I got this thing i'm trying to solve:
I got a ListView created using Wicket ( 1.5 ) with a lot of elements and a scroll. When new items are available, the user is asked if he would like to refresh the list via a message backed by an AjaxLink:
public void onClick(AjaxRequestTarget ajaxTarget) {
/* do something ... */
ajaxTarget.addComponent(_list);
}
So on click the list gets reloaded and the scroll position is reset to zero. Is there any way i can call JavaScript before the list reloads the save the scroll position?
(I know how to get/save the scroll position ( .scrollTop() ) , i just don't know how to call a function right before AJAX ).
Have a look at the AjaxCallDecorator class to decorate the script before and after the ajax call.
You can have a look at my answer there : https://stackoverflow.com/a/10499868/722952
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.
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);
}
}
I am retrieving a List<String> strings from my database and i would like to display it in a Flex Table.Also with every row in the flex table i want a delete button.The delete button on click should remove the row from the flex table.
so i write code some thing similar to
for(int i =0 ;i < strings.size();i++) {
flexTable.setWidget(i,0,strings.get(i));
flexTable.setWidget(i,1,new Button("X");
}
Now i am using MVP architecture to write this code.The reason why i am specifying this is i want all the widgets declared in my View and the click handlers to be in my presenter.
Generally if i have Button b = new Button("Sample Button"); in my View
I can have a getter method and use getButton.addClickHandler(new ClickHandler())
in my presenter.
But here i am creating delete buttons on fly.
So how can i assign a click handler to the delete Button and onClick i should be able to remove the row from the flextTable.
Thanks
Just register the handlers in the View and provide a Callback type class from the Presenter that receives each String that is deleted.