Wicket 7 - AutoCompleted Text field - to have onSelect method - wicket

We would like to implement AutoCompleteTextField field, once user has selected the field from AutoComplete result, then system would auto populate on other text field, i have used the component AjaxFormComponentUpdatingBehavior (blur), however this will take effect on every text input from AutoCompleteTextField field, but if i change to AjaxFormComponentUpdatingBehavior (change), it doesnt work.
Below is the sample code:
AutoCompleteTextField<String> field_postcode = new AutoCompleteTextField<String>("field_postcode",
new PropertyModel<String>(getModelObject(), "wAdditionalInfo.postal"), autoCompleteRenderer) {
private static final long serialVersionUID = 1L;
#Override
protected Iterator<String> getChoices(String input) {
if (Strings.isEmpty(input)) {
List<String> emptyList = Collections.emptyList();
return emptyList.iterator();
}
List<String> choices = new ArrayList<String>();
List<Postcode> postcodeList = getProfileManager().findAllPostcodeByPostcode(input);
for (Postcode p : postcodeList) {
String postcode = p.getPostcode();
if (postcode.startsWith(input)) {
choices.add(p.getPostcode());
if (choices.size() == 10) {
break;
}
}
}
return choices.iterator();
}
};
field_postcode.setRequired(true);
field_postcode.add(new AjaxFormComponentUpdatingBehavior("blur"){
private static final long serialVersionUID=-1107858522700306810L;
#Override protected void onUpdate( AjaxRequestTarget target){
Postcode postcode = getProfileManager().findPostcodeByPostcode(field_postcode.getInput());
if (postcode != null) {
City city = postcode.getCity();
State state = city.getState();
field_city.setModelObject(city.getCity());
ddl_state.setModelObject(state);
if (isDisplayTip) {
//isDisplayTip true mean is from widrawal webform
isReadonly = true;
} else {
field_city.setEnabled(false);
}
ddl_state.setEnabled(false);
} else {
if (isDisplayTip) {
isReadonly = false;
} else {
field_city.setEnabled(true);
}
ddl_state.setEnabled(true);
}
target.add(field_city, ddl_state);
}
}
);
Is there any api from wicket to achieve this? We need to have something when user select the option from Auto complete, then it only onUpdate method of AjaxFormComponentUpdatingBehavior

According to https://github.com/apache/wicket/blob/cbc237159c4c6632b4f7db893c28ab39d1b40ed4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/wicket-autocomplete.js#L620 it should trigger change event on the HTMLInputElement and thus notify you on the server side.
Use the browser debugger to see whether https://github.com/apache/wicket/blob/cbc237159c4c6632b4f7db893c28ab39d1b40ed4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/wicket-autocomplete.js#L453 is executed and whether it leads to an Ajax call with the value in the parameters.

Related

GXT 3 GridRowEditing SimpleComboBox entries not displayed

i'm currently using a GXT3 grid to display data from a custom object EntityDAO.
This class contains 3 attributes: an id and two references to complex type objects
Let's call them
Long id;
UserInfo userInfo;
OutputInfo outputInfo;
I created an interface to explicit the desired display of these info:
interface EntityDAOProperties extends PropertyAccess<EntityDAO> {
ModelKeyProvider<EntityDAO> id();
#Path("userInfo.name")
ValueProvider<EntityDAO, String> step();
#Path("outputInfo.name")
ValueProvider<EntityDAO, String> outputInfo();
}
The display is perfectly fine. The matter is that i want to be able to add/edit rows to my grid.
To do so, I have a
GridRowEditing<EntityDAO> editing = createGridEditing(grid);
comprising a
SimpleComboBox<String> comboUser = new SimpleComboBox<String>(new LabelProvider<String>() {
#Override
public String getLabel(String item) {
return item;
}
});
for(...){
comboUser.add("entry " + i); // For instance
logger.info("entry : " +i); // For instance
i++;
}
comboUser.setEditable(false);
comboUser.setTriggerAction(TriggerAction.ALL);
When i double click on my line and make the GridRowEditing appear, the combo doesn't seem to have more than 1 row and the click on the expand arrow doesn't change anything to the matter.
I think you miss the part where you set the property editor for the combobox, here is the example code:
SimpleComboBox<Light> combo = new SimpleComboBox<Light>(new StringLabelProvider<Light>());
combo.setClearValueOnParseError(false);
combo.setPropertyEditor(new PropertyEditor<Light>() {
#Override
public Light parse(CharSequence text) throws ParseException {
return Light.parseString(text.toString());
}
#Override
public String render(Light object) {
return object == null ? Light.SUNNY.toString() : object.toString();
}
});
combo.setTriggerAction(TriggerAction.ALL);
combo.add(Light.SUNNY);
combo.add(Light.MOSTLYSUNNY);
combo.add(Light.SUNORSHADE);
combo.add(Light.MOSTLYSHADY);
combo.add(Light.SHADE);
// combo.setForceSelection(true);
editing.addEditor(cc2, new Converter<String, Light>() {
#Override
public String convertFieldValue(Light object) {
return object == null ? "" : object.toString();
}
#Override
public Light convertModelValue(String object) {
try {
return Light.parseString(object);
} catch (ParseException e) {
return null;
}
}
}, combo);
Hope this could help you.

How to implement something like a wizard screen?

I want to place a "Next" button which , when clicked , will display another group of components ; and I want also to place a "Previous" button which , when clicked , then display the previous group of components. How to achieve that ?
I recently implemented forms for data entry. Typically i have a wizard class that holds all the forms in the wizard, so i can easily navigate back and forth between them. And when i call a new form, i pass along the object of the wizard.
Below is my wizard, with implementation omitted.
public final class ReportWizard {
public static ReportWizard instance = null;
Form parent = null;
Form titleForm = null;
Form budgetForm = null;
Form iconForm = null;
final Report reports[] = new Report[20];
public ReportWizard(Form parent) {
this.parent = parent;
this.instance = this;
}
void getTitle() {
AddReportForm reportForm = new AddReportForm(parent, this);
reportForm.showReportForm();
titleForm = reportForm;
ImageListPicker getIcon = new ImageListPicker(titleForm, reports, this);
iconForm = getIcon.imageListForm;
}
void getIcon() {
iconForm.show();
}
public void cancelWizard() {
titleForm = null;
iconForm = null;
budgetForm = null;
instance = null;
parent.show();
parent = null;
System.gc();
}
}

MultiAutoCompleteTextField for Wicket

I need an AutoCompleteTextField for Wicket which can handle several autocomplete items separated by a comma.
Something like this: http://digitarald.de/project/autocompleter/1-1/showcase/delicious-tags/
Wicket-extensions provides autocomplete features.
Add an AutoCompleteBehavior to the TextArea in the same fashion AutoCompleteTextField uses it.
For instance:
TextArea t = new TextArea("area", new Model());
AutoCompleteBehavior<String> b = new AutoCompleteBehavior<String>(
StringAutoCompleteRenderer.INSTANCE){
#Override
protected Iterator<String> getChoices(String input) {
return getMyListElements().iterator();
}
};
t.setOutputMarkupId(true);
t.add(b);
add(t);
If you are using Maven, just add the following dependency to start using wicket-extensions:
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-extensions</artifactId>
<version>${wicket.version}</version>
</dependency>
EDIT
Seeing that the question is about Multi autocomplete textfields, like the one in this example, you might find the following link useful: Wicket auto-complete text fields. There are a couple of components in there that seem to do just what you need.
You might also find this discussion and this one in the Apache Wicket User list useful. You'll find a couple of links there to projects that seem to also have this component: interwicket and WicketHub
Also see https://github.com/wicketstuff/core/tree/master/jdk-1.5-parent/autocomplete-tagit-parent
I could resolve the problem by Ajax in wicket as the following
TextArea partnersDB = new TextArea("partnersDB");
String partnerKeeper;
public String getPartnerKeeper() {
return partnerKeeper;
}
public void setPartnerKeeper(String partnerKeeper) {
this.partnerKeeper = partnerKeeper;
}
public String getMessageTypeKeeper() {
return messageTypeKeeper;
}
public void setMessageTypeKeeper(String messageTypeKeeper) {
this.messageTypeKeeper = messageTypeKeeper;
}
private void makePartnersAutoCompleter() {
final List<String> allPartners = auditDAO.findAllPartnerIds();
IAutoCompleteRenderer partnerRenderer = new AbstractAutoCompleteRenderer() {
#Override
protected String getTextValue(Object obj) {
return getPartnerKeeper() + ((String) obj);
}
#Override
protected void renderChoice(Object obj, Response r, String str) {
r.write((String) obj);
}
};
AutoCompleteBehavior autoCompleteBehavior = new AutoCompleteBehavior(partnerRenderer) {
#Override
protected Iterator<String> getChoices(String input) {
int lastCommaIndex = input.lastIndexOf(';');
String realInput = "";
if (lastCommaIndex == -1) {
setPartnerKeeper("");
realInput = input;
} else {
setPartnerKeeper(input.substring(0, lastCommaIndex) + ";");
realInput = input.substring(lastCommaIndex + 1);
}
List<String> completions = new ArrayList<String>();
for (int i = 0; i < allPartners.size(); i++) {
String partner = allPartners.get(i);
if (partner.startsWith(realInput.toUpperCase()) || partner.startsWith(realInput.toLowerCase())) {
completions.add(partner + ";");
}
}
return completions.iterator();
}
};
partnersDB.add(autoCompleteBehavior);
}

How to apply like search on GWT cell table?

I am using GWT 2.3.I which I am using GWT cell table.
Here below is the code for my cell table:
public class FormGrid extends SuperGrid {
List<Form> formList;
#Override
public void setColumns(CellTable table) {
TextColumn<Form> nameColumn = new TextColumn<Form>() {
#Override
public String getValue(Form object) {
return object.getName();
}
};
table.addColumn(nameColumn, "Name");
}
#Override
public void setData() {
if (formList != null && formList.size() > 0) {
AsyncDataProvider<Form> provider = new AsyncDataProvider<Form>() {
#Override
protected void onRangeChanged(HasData<Form> display) {
int start = display.getVisibleRange().getStart();
int end = start + display.getVisibleRange().getLength();
end = end >= formList.size() ? formList.size() : end;
List<Form> sub = formList.subList(start, end);
updateRowData(start, sub);
}
};
provider.addDataDisplay(getTable());
provider.updateRowCount(formList.size(), true);
}
}
public List<Form> getFormList() {
return formList;
}
public void setFormList(List<Form> formList) {
this.formList = formList;
}
}
In this my set column and set data will be called fro super class flow.This cell table is working fine.
Now I want to put a filter type facility (like search) in this cell table.It should be like, there is a texbox above the cell table and what ever written in that text box, it should fire a like query to all form name for that text box value.
for example I have 1000 form in the grid.Now if user writes 'app' in some filter textbox above the cell table the all the form which have 'app' in there name will be filtered and grid has only those forms only.
This is the first case:
Another case is I am only render one column in grid name.I have two more properties in form (description,tag).But I am not rendering them.now for filter if user writes 'app' in filter box then it should make a query to all three (name, description, and tag) and should return if 'app' matched to any of three.
I am not getting how to apply filter in cell table.
Please help me out.Thanks in advance.
You can find an implementation in the expenses sample.
Here is a short summary of the steps
1.) Create a Textbox and a SearchButton.
2.) add a clickHandler to the SearchButton (You can also add KeyUpHandler to the Textbox alternatively)
searchButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
search();
}
});
3.) In the search function retrieve the searchString and store it.
private void search() {
searchString = searchBox.getText();
setData();
}
4.) modify your setdata() function to take searchString into account
#Override
public void setData() {
if (formList != null && formList.size() > 0) {
AsyncDataProvider<Form> provider = new AsyncDataProvider<Form>() {
#Override
protected void onRangeChanged(HasData<Form> display) {
int start = display.getVisibleRange().getStart();
int end = start + display.getVisibleRange().getLength();
//new function if searchString is specified take into account
List<Form> sub = getSubList(start,end);
end = end >= sub.size() ? sub.size() : end;
updateRowData(sub.subList(start, end);, sub);
}
};
provider.addDataDisplay(getTable());
provider.updateRowCount(formList.size(), true);
}
}
private List<Form> getSubList(int start, int end) {
List<Form> filtered_list = null;
if (searchString != null) {
filtered_list= new ArrayList<Form>();
for (Form form : formList) {
if (form.getName().equals(searchString) || form.getTag().equals(searchString) || form.getDescription().equals(searchString))
filtered_list.add(form);
}
}
else
filtered_list = formList;
return filtered_list;
}
can propose another solution what can be used quite easy multiple times.
Idea is to create custom provider for your celltable.
GWT celltable filtering
Video in this post shows it in action.
Here is the part of code of custom list data provider which u have to implement.
#Override
protected void updateRowData(HasData display, int start, List values) {
if (!hasFilter() || filter == null) { // we don't need to filter, so call base class
super.updateRowData(display, start, values);
} else {
int end = start + values.size();
Range range = display.getVisibleRange();
int curStart = range.getStart();
int curLength = range.getLength();
int curEnd = curStart + curLength;
if (start == curStart || (curStart < end && curEnd > start)) {
int realStart = curStart < start ? start : curStart;
int realEnd = curEnd > end ? end : curEnd;
int realLength = realEnd - realStart;
List<t> resulted = new ArrayList<t>(realLength);
for (int i = realStart - start; i < realStart - start + realLength; i++) {
if (filter.isValid((T) values.get(i), getFilter())) {
resulted.add((T) values.get(i));
}
}
display.setRowData(realStart, resulted);
display.setRowCount(resulted.size());
}
}
}

Wicket children panels refresh

I'm just looking for extra pair of eyes to spot why children panels do not show up/change visibility on radio button selection/change that does call for their refresh
public class OptionsPanel extends Panel {
private AutoCompleteSearchField departureField;
private HiddenField departureCodeField;
private CompoundPropertyModel model;
private RadioGroup flightChoices;
private RadioGroup dateChoices;
private final TripSearchModel tripSearchModel;
private WebMarkupContainer optionsContainer;
private FlexibleDates flexibleDates;
private FixedDates fixedDates;
private PassengersAndClass passengersAndClass;
private static List FIX_CONTAINER_VISIBLE = Lists.newArrayList(true, false, true);
private static List FLEX_CONTAINER_VISIBLE = Lists.newArrayList(false, true, true);
private static List HIDE_CONTAINERS = Lists.newArrayList(false, false, false);
public OptionsPanel(String id, CompoundPropertyModel model) {
super(id);
this.model = model;
this.tripSearchModel = (TripSearchModel) model.getObject();
add(departureLabel());
add(departureField());
add(departureCodeField());
add(flightType());
add(travellingWhen());
add(dateType());
add(optionsContainer(HIDE_CONTAINERS));
}
private Component departureLabel() {
return new WebMarkupContainer("departureLabel").setOutputMarkupId(true);
}
private AutoCompleteSearchField departureField() {
departureField = new AutoCompleteSearchField("departureField", "From", "flightFromField", null, true, model.bind("departure"));
departureField.setOutputMarkupId(true);
departureField.add(new CityValidator(this, departureCodeField));
return departureField;
}
private HiddenField departureCodeField() {
departureCodeField = new HiddenField("departureCodeField", model.bind("departureCode"));
departureCodeField.setMarkupId("departureFieldCode");
return departureCodeField;
}
private Component flightType(){
flightChoices = new RadioGroup("flightTypes");
flightChoices.setModel(model.bind("tripType"));
flightChoices.add(listOfRadio(flightsTypeList(), "flightType"));
return flightChoices;
}
private List flightsTypeList() {
return Arrays.asList(
new RadioOptionObject("one way", new Model(TRIP_TYPE_ONE_WAY)),
new RadioOptionObject("return", new Model(TRIP_TYPE_RETURN))
);
}
private Component travellingWhen(){
return new Label("travellingWhen", new StringResourceModel("travelling_when", this, new Model("")).getString());
}
private Component dateType(){
dateChoices = new RadioGroup("dateTypes");
dateChoices.setModel(model.bind("dateType"));
dateChoices.add(listOfRadio(datesTypeList(), "dateType"));
return dateChoices;
}
private List datesTypeList() {
return Arrays.asList(
new RadioOptionObject("Flexible dates", new Model(DATE_TYPE_FLEX)),
new RadioOptionObject("Fixed dates", new Model(DATE_TYPE_FIX)));
}
private ListView listOfRadio(final List flightDateOptionValues, final String componentId) {
ListView listView = new ListView(componentId + "sList", flightDateOptionValues) {
#Override
protected void populateItem(final ListItem listItem) {
final Radio radio = new Radio(componentId + "Radio", ((RadioOptionObject) listItem.getModelObject()).getRadioModel()) {
#Override
public String getValue() {
return listItem.getDefaultModelObjectAsString();
}
#Override
protected boolean getStatelessHint() {
return true;
}
};
radio.add(new AjaxEventBehavior("onchange") {
#Override
protected void onEvent(AjaxRequestTarget target) {
tripSearchModel.setDateType(radio.getModelObject().toString());
refreshPanel(target);
}
});
listItem.add(radio);
listItem.add(new Label(componentId + "Name", new StringResourceModel(radio.getModelObject().toString(), this, radio.getModel())));
}
};
return listView;
}
private void refreshPanel(AjaxRequestTarget target) {
this.remove(optionsContainer);
target.addComponent(optionsContainer(visibility()));
}
private List visibility() {
return visibilityMode(((TripSearchModel) model.getObject()).getDateType());
}
private Component optionsContainer(List visibility){
optionsContainer = new WebMarkupContainer("optionsContainer");
optionsContainer.add(flexibleDates(visibility.get(0)));
optionsContainer.add(fixedDates(visibility.get(1)));
optionsContainer.add(passengersAndClass(visibility.get(2)));
optionsContainer.setOutputMarkupId(true);
optionsContainer.setVisible(true);
return optionsContainer;
}
private Component flexibleDates(Boolean visibility){
flexibleDates = new FlexibleDates("flexibleDates", model);
flexibleDates.setOutputMarkupId(true);
flexibleDates.setVisible(visibility);
return flexibleDates;
}
private Component fixedDates(Boolean visibility){
fixedDates = new FixedDates("fixedDates", model);
fixedDates.setOutputMarkupId(true);
fixedDates.setVisible(visibility);
return fixedDates;
}
private Component passengersAndClass(Boolean visibility){
passengersAndClass = new PassengersAndClass("passengersAndClass", model);
passengersAndClass.setOutputMarkupId(true);
passengersAndClass.setVisible(visibility);
return passengersAndClass;
}
private List visibilityMode(String dateType) {
if(DATE_TYPE_FIX.equalsIgnoreCase(dateType)){
return FIX_CONTAINER_VISIBLE;
} else if(DATE_TYPE_FLEX.equalsIgnoreCase(dateType)){
return FLEX_CONTAINER_VISIBLE;
} else{
return HIDE_CONTAINERS;
}
}
}
I think one potential issue you may have is that you listen for ajax-onchange events and you attempt to make changes to panels depending on the model supposedly having changed. In my experience with radio-type form components, you may need to use AjaxFormComponentUpdatingBehavior (instead of AjaxEventBehavior) in order to capture changes to a model of such form-components. Hope this helps!
Edit: Instead of listing caveats (you need to use another type of behavior for some form components), I'll just add a link to the documentation: Javadoc for AjaxFormComponentUpdatingBehavior
At the end of the day I find out that there was another Easter egg hidden for me.
radio.add(new AjaxEventBehavior("onchange") {
#Override
protected void onEvent(AjaxRequestTarget target) {
tripSearchModel.setDateType(radio.getModelObject().toString());
refreshPanel(target);
}
I was changing same date parameter on event of two different radio groups, which rendered form useless. That was one change, the second change was moving from WebMarkupContainer to EnclosureContainer that was suggested to use on Wicket mailing list for components changing their visibility status. Nevertheless I will give it a try with AjaxFormComponentUpdatingBehavior thank you #Martin Peters