wicket issue unable to move items from one listmultiplechoice another - wicket

I have a Wicket Panel. It has two text fields adjacent to each other and two ListMultipleChoice controls adjacent to each other and two buttons "add and remove" in between two these ListMultipleChoice's.
I was unable to move the items from one list box to another unless I entered some values in text fields, which were prior to the list boxes.
If values were entered in text fields, I was able to move the items.
Please find the code below.
TextField<BigDecimal> textfield1 = new TextField<BigDecimal>("value1")
{
private static final long serialVersionUID = 8199976201679629866L;
#Override
public IConverter getConverter(Class<?> type) {
return new FixedDecimalPlacesConverter();
}
};
textfield1.setType(BigDecimal.class);
textfield1.setLabel(new Model<String>("Value1"));
textfield1.setRequired(true)
.add(PositiveNumberValidator.getInstance())
.add(new FixedDecimalPlacesValidator(2));
add(new FeedBackBorder("Border1").add(textfield1));
TextField <BigDecimal> textfield2 = new TextField<BigDecimal>("value2")
{
private static final long serialVersionUID = 8199976201679629866L;
#Override
public IConverter getConverter(Class<?> type) {
return new FixedDecimalPlacesConverter();
}
};
textfield2.setType(BigDecimal.class);
textfield2.setOutputMarkupId(true);
textfield2.setLabel(new Model<String>("Value2"));
textfield2.setRequired(true)
.add(PositiveNumberValidator.getInstance())
.add(new FixedDecimalPlacesValidator(2));
add (new FeedBackBorder("Border2").add(textfield2));
ChoiceRenderer<UserBean> choiceRenderer = new ChoiceRenderer<UserBean>("userName", "userID.ID");
availableUsers= new ListMultipleChoice<UserBean>( "availableUsersBean", availableUsersList, choiceRenderer );
availableUsers.setOutputMarkupId(true);
availableUsers.setLabel(new Model<String>("Available Users"));
add(new FeedBackBorder("availableUsersBorder").add(availableUsers));
selectedUsers = new ListMultipleChoice<UserBean>( "selectedUsersBean", selectedUsersList, choiceRenderer );
selectedUsers.setOutputMarkupId(true);
selectedUsers.setLabel(new Model<String>("Selected Users"));
add(new FeedBackBorder("selectedUsers Border").add(selectedUsers ));
add = new AjaxButton("add") {
#Override
protected void onSubmit(AjaxRequestTarget target, Form form) {
update(target, availableUsers.getModelValue(),availableUsers, selectedUsers);
}
};
add(new FeedBackBorder("addBorder").add(add));
remove = new AjaxButton("remove") {
#Override
protected void onSubmit(AjaxRequestTarget target, Form form) {
update(target, selectedUsers.getModelValue(), selectedUsers , availableUsers);
}
};
add(new FeedBackBorder("removeBorder").add(remove));
What could be the issue?

add.setDefaultFormProcessing(false);
remove.setDefaultFormProcessing(false);
I am using org.apache.wicket.markup.html.form.Button which allows you to turn off full form submit with button click with the setDefaultFormProcessing(boolean). This should allow you to process actions without submitting your complete form, therefore not validating required textfields.

At a first glance: Your TextFields are required. Submitting the Form via AjaxButtons wouldn't trigger the onSubmit method for an invalid form but the onError method.
Possible Solutions (in no particular order):
Moving the Lists to a nested form
Moving the contents of the onSubmit to a separate method and call it from onError too
Move the item moving logic to a pure JavaScript based Behaviour or Decorator that doesn't trigger a form submit.

Related

checkbox not getting unchecked in wicket

I have a checkgroup and on selecting a checkbox in the group I want to get the number of selected/checked check boxes.
By the below code, I am able to get the selected number of checkboxes but on unchecking or removing the selection, i see that its still selected.
Example : I have selected 2 now I get 2 string selected.
Now I unselect one checkbox, even now i get 2 strings selected. While I expect one string to be checked.
The code is given below:
final CheckGroup myGroup = new CheckGroup("group", new ArrayList()) {
#Override
protected Collection<String> convertValue(String[] values) throws ConversionException {
Collection<String> myCollection = super.convertValue(values);
checkedString.addAll(myCollection);
HashMap<Integer, String> myTempList = new HashMap<Integer, String>();
for (String myString : checkedString) {
myTempList.put(myString.getSystemId(), myString);
}
checkedString.clear();
for (Entry<Integer, String> myEntry : myTempList.entrySet()) {
checkedString.add(myEntry.getValue());
}
return checkedString;
}
#Override
protected void onSelectionChanged(Collection newSelection) {
newSelection = checkedString;
}
#Override
protected boolean wantOnSelectionChangedNotifications() {
return true;
}
};
add(myForm);
myForm.add(myGroup);
Add a behavior to your component
sampleChckbox.add(new AjaxFormComponentUpdatingBehavior("onclick"){
#Override
protected void onUpdate(AjaxRequestTarget target) {
//perform your operation here
}
This method will fire an Ajax request on "onClick" event; which will update your backend logic at runtime
edit :
To be very specific to CheckGroup class use the AjaxFormChoiceComponentUpdatingBehavior
AjaxFormChoiceComponentUpdatingBehavior is the behavior to use with CheckGroups and RadioGroups. If you used an AjaxFormComponentUpdatingBehavior with the onchange event, you'd run into this bug with IE
. AjaxFormChoiceComponentUpdatingBehavior handles this properly, adding onclick event handlers to each of the Checks in the CheckGroup.
As a side note, what Igor stated in that mail, is that CheckBox can be replaced with AjaxCheckBox, not Check. AjaxCheckBox is nothing more than a convenience subclass of CheckBox with an AjaxFormComponentUpdatingBehavior("onclick"), as the sources show.

How can I observe the changed state of model items in an ObservableList?

I have an ObservableList of model items. The model item is enabled for property binding (the setter fires a property changed event). The list is the content provider to a TableViewer which allows cell editing. I also intend to add a way of adding new rows (model items) via the TableViewer so the number of items in the list may vary with time.
So far, so good.
As this is all within an eclipse editor, I would like to know when the model gets changed. I just need one changed event from any changed model item in order to set the editor 'dirty'. I guess I could attach some kind of listener to each individual list item object but I wonder if there is a clever way to do it.
I think that I might have a solution. The following class is an inline Text editor. Changes to the model bean (all instances) are picked up using the listener added in doCreateElementObservable. My eclipse editor just needs to add its' own change listener to be kept informed.
public class InlineEditingSupport extends ObservableValueEditingSupport
{
private CellEditor cellEditor;
private String property;
private DataBindingContext dbc;
IChangeListener changeListener = new IChangeListener()
{
#Override
public void handleChange(ChangeEvent event)
{
for (ITableEditorChangeListener listener : listenersChange)
{
listener.changed();
}
}
};
public InlineEditingSupport(ColumnViewer viewer, DataBindingContext dbc, String property)
{
super(viewer, dbc);
cellEditor = new TextCellEditor((Composite) viewer.getControl());
this.property = property;
this.dbc = dbc;
}
protected CellEditor getCellEditor(Object element)
{
return cellEditor;
}
#Override
protected IObservableValue doCreateCellEditorObservable(CellEditor cellEditor)
{
return SWTObservables.observeText(cellEditor.getControl(), SWT.Modify);
}
#Override
protected IObservableValue doCreateElementObservable(Object element, ViewerCell cell)
{
IObservableValue value = BeansObservables.observeValue(element, property);
value.addChangeListener(changeListener); // ADD THIS LINE TO GET CHANGE EVENTS
return value;
}
private List<ITableEditorChangeListener> listenersChange = new ArrayList<ITableEditorChangeListener>();
public void addChangeListener(ITableEditorChangeListener listener)
{
listenersChange.remove(listener);
listenersChange.add(listener);
}
public void removeChangeListener(ITableEditorChangeListener listener)
{
listenersChange.remove(listener);
}
}

Wicket - changing panels through a dropdown

I have a dropdown component added on a page. the purpose of this dropdown is to change the type of input form that is rendered. for example, different forms have different required fields, editable fields, etc.
public final class Test extends WebPage
{
CustomPanel currentPanel = new MeRequest("repeater",FormType.MIN);
public Test(PageParameters parameters)
{
add(currentPanel);
DropDownChoice ddc = new DropDownChoice("panel", new PropertyModel(this, "selected"), panels, choiceRenderer);
ddc.add(new AjaxFormComponentUpdatingBehavior("onchange") {
protected void onUpdate(AjaxRequestTarget target) {
System.out.println("changed");
currentPanel = new MeRequest("repeater",FormType.PRO);
target.add(currentPanel);
}
});
add(ddc);
}
i've tried various options with limited results. the only real success has been updating the model, but what i really want to do is change how the components behave.
any thoughts on what i'm missing?
1) If you want to replace one panel with another you may just do the following.
First of all, you should output the markup id of the original panel:
currentPanel.setOutputMarkupId(true);
And then in the ajax event handler write something like that:
protected void onUpdate(AjaxRequestTarget target) {
CustomPanel newPanel = new MeRequest("repeater", FormType.PRO);
currentPanel.replaceWith(newPanel);
currentPanel = newPanel;
currentPanel.setOutputMarkupId(true);
target.addComponent(currentPanel);
}
In this case with every change of dropdown choice you add new panel to the page and you remove old panel from the page.
2) But I would proposed a slightly different approach to your problem. You should move the construction logic of your panel to the onBeforeRender() method:
public class MeRequest extends Panel {
private FormType formType;
public MeRequest(String id, FormType formType) {
super(id);
this.formType = formType;
// don't forget to output the markup id of the panel
setOutputMarkupId(true);
// constructor without construction logic
}
protected void onBeforeRender() {
// create form and form components based on value of form type
switch (formType) {
case MIN:
// ...
break;
case PRO:
// ...
break;
}
// add form and form components to panel
addOrReplace(form);
form.add(field1);
form.add(field2);
// ...
super.onBeforeRender();
}
public void setFormType(FormType formType) {
this.formType = formType;
}
}
Then you'll be able to only change type of the panel in the ajax event:
protected void onUpdate(AjaxRequestTarget target) {
currentPanel.setFormType(FormType.PRO);
target.addComponent(currentPanel);
}
Thus we rebuilt the original panel without recreating it.

How to programmatically open a gwt listbox?

I have a user form with a lot of gwt listbox. The form is like an excel form with named list.
It's ugly and the arrows take place.
I would like the cells were like in excel. The arrow appears only when you click in the cell.
I start to program my own widget with a textbox and a listbox embedded into a DeckPanel, switching when you click on the textbox or when the value change. But with this solution, it is necessary to click again to open the listbox.
Now, it will be great, if when you click on the textbox, the listbox will be displayed already open.
In the code below, I try to do this into the method onClick wih this line:
DomEvent.fireNativeEvent(event.getNativeEvent(), listBox);
But it has no effects.
public class CustomListBox extends Composite implements ClickHandler,
ChangeHandler, HasChangeHandlers {
private final StringListBox listBox;
private final TextBox textBox;
private final DeckPanel panel;
public CustomListBox() {
textBox = new TextBox();
textBox.addClickHandler(this);
textBox.setReadOnly(true);
listBox = new StringListBox();
listBox.addChangeHandler(this);
panel = new DeckPanel();
panel.add(textBox);
panel.add(listBox);
panel.showWidget(0);
// All composites must call initWidget() in their constructors.
initWidget(panel);
}
#Override
public void onClick(ClickEvent event) {
Object sender = event.getSource();
if (sender == textBox) {
panel.showWidget(1);
DomEvent.fireNativeEvent(event.getNativeEvent(), listBox);
}
}
public void addItem(String item) {
listBox.addItem(item);
}
public int getSelectedIndex() {
return listBox.getSelectedIndex();
}
public String getItemText(int selectedIndex) {
return listBox.getItemText(selectedIndex);
}
#Override
public HandlerRegistration addChangeHandler(ChangeHandler handler) {
return listBox.addChangeHandler(handler);
}
#Override
public void onChange(ChangeEvent event) {
Object sender = event.getSource();
if (sender == listBox) {
textBox.setText(getItemText(getSelectedIndex()));
panel.showWidget(0);
}
}
}
Since you are already programming your own widget, why don't you go all the way. Don't swap out the text box for a list box widget. Instead of a textbox use a label. Add an arrow to your label background when you mouse over, then use a popupPanel for the list itself. In the popupPanel you can make the list items whatever you like, just make sure when you click on it, it sets the text in your original label.

Gwt form question

I have a gwt form which has about 70-100 widgets (textboxes,listboxes,custom widgets etc)
I am trying to implement the features of CUT ,COPY in this form .For this i have 2 buttons right on top of the form.
Now the problem i have is that when i click on the copy button , the widget that was focused in the form looses focus and i dont know which text to copy(or which widget was last focused before the focus getting to the copy button)
I was planning to implement blur handlers on all the widgets but i feel is a very laborious and not a good solution.
How can i get around this issue?
Thanks
Perhaps someone with a deeper insight might provide a better approach but I beleive adding blur handlers is perfectly valid. I do not quite see why you think it would be laborious, after all you don't need a different handler for each of your widgets, you can get away with only one(at most a couple for a variety of controls..), here is a very simple example,
public class CustomBlurHandler implements BlurHandler{
Object lastSource;
String text;
#Override
public void onBlur(BlurEvent event) {
if (event.getSource() instanceof TextBox) {
lastSource = event.getSource();
text = textBox.getSelectedText();
}
}
public Object getLastSource() {
return lastSource;
}
public String getText() {
return text;
}
}
and onModuleLoad :
public class Test implements EntryPoint {
CustomBlurHandler handler = new CustomBlurHandler();
public void onModuleLoad() {
TextBox text1 = new TextBox();
TextBox text2 = new TextBox();
text1.addBlurHandler(handler);
text2.addBlurHandler(handler);
Button b = new Button("Get last selected text");
b.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert(handler.getLastSource()+ " " + handler.getText());
}
});
RootPanel.get().add(text1);
RootPanel.get().add(text2);
RootPanel.get().add(b);
}
}