How to get value of model in wicket behavior - java

in my form I have input text and then dataView:
private class RegistrationForm extends Form<Table> {
private static final long serialVersionUID = 1L;
public RegistrationForm(final Table table) {
super("registrationForm", new CompoundPropertyModel<Table>(table));
setOutputMarkupId(true);
final TextField<String> text = new TextField<String>("name");
add(text);
DataView<Player> dataView = new DataView<Player>("rows", playerDataProvider) {
private static final long serialVersionUID = 1L;
#Override
protected void populateItem(final Item<Player> listItem) {
...
on listItem I add ajaxEventBehavior when I double Click on row:
listItem.add(new AjaxEventBehavior("ondblclick") {
private static final long serialVersionUID = 1L;
#Override
protected void onEvent(final AjaxRequestTarget target) {
System.out.println(table.getName());
}
});
Problem is when I double click on table it print null not the value which I have in input TextField. Why ?
I try to update model:
text.updateModel();
or get value from text:
System.out.println(table.getName() + "bbbbbbbbbbbbbbbbb" + text.getInput() + "vv"
+ text.getValue() + "ff");
but with no success.
in form I have also submit button and when I press it every think works. I have problems just with double click

AjaxEventBehavior itself does not submit the form, so you're not getting the text field value. You can use one of the following subclasses instead:
AjaxFormComponentUpdatingBehavior will submit only the one FormComponent it is attached to. It needs to be attached to a FormComponent, so you'll have to use the following if you want to attach it to the entire ListItem:
AjaxFormSubmitBehavior will submit the entire form. This is probably what you need here.
All these behaviors are included in Wicket and their Javadoc is right there with the source code. For the Ajax stuff, check subclasses of AbstractAjaxBehavior, in particular the subclasses of AjaxEventBehavior.

Related

TableViewer does not update the default value of a cell

I have a UI bug in a legacy code in our Java project. We display a table, with three columns (HumanReadable, name and value) in a window. In that window, users can click on each cell and update the values. Before that, user clicks the "add" button to add a new row (three new cells). Each cell has a default value, until the user decides to update the value. Now, when the users decides to update the value of the cell, he clicks on the cell and types in the value. The bug is that, once done editing, it keeps the default value in the UI. In the backend, the value has changed (if you click the cell again, it will go into editing mode and show you the value).
I uploaded a short GIF that shows the issue and can be found here.
In that GIF you can see that I updated the default value of the first column to be test. Then I click some other place (to exit the edit mode) and it showed the default value instead of test in the first column.
The method that creates the table:
private void createTable(final Composite parent) {
final Table varTable = new Table(parent, SWT.MULTI);
varTable.setHeaderVisible(true);
varTable.setLinesVisible(true);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(varTable);
varTableViewer = new TableViewer(varTable);
final DataBindingContext bindingContext = new DataBindingContext();
final TableViewerColumn col1 = GuiUtils.createTableColumn(varTableViewer, "Human Readable");
col1.setEditingSupport(new StringEditingSupport(varTableViewer, bindingContext, dataProperty));
col1.getColumn().setWidth(120);
final TableViewerColumn col2 = GuiUtils.createTableColumn(varTableViewer, "Name");
col2.getColumn().setWidth(120);
col2.setEditingSupport(new StringEditingSupport(varTableViewer, bindingContext, nameProperty));
final TableViewerColumn col3 = GuiUtils.createTableColumn(varTableViewer, "Value");
col3.setEditingSupport(new StringEditingSupport(varTableViewer, bindingContext, valueProperty));
KeyBoardNavigationSupport.createSupport(varTableViewer);
input = new WritableList(globalVars, FlowVar.class);
ViewerSupport.bind(varTableViewer, input, BeanProperties.values(new String[] { dataProperty, nameProperty, valueProperty }));
}
The StringEditingSupport class:
public class StringEditingSupport extends ObservableValueEditingSupport {
private class CellEditorPrintValidatorErrors extends TextCellEditor {
public CellEditorPrintValidatorErrors(Composite control) {
super(control);
}
#Override
protected void focusLost(){
if(this.getErrorMessage() != null) {
MessageDialog.openError(this.getControl().getShell(), "Invalid input", this.getErrorMessage());
}
}
}
private final CellEditor cellEditor;
String propertyName;
public StringEditingSupport(final ColumnViewer viewer, final DataBindingContext dbc, final String propertyName) {
super(viewer, dbc);
cellEditor = new TextCellEditor((Composite) viewer.getControl());
this.propertyName = propertyName;
}
public StringEditingSupport(final ColumnViewer viewer, final DataBindingContext dbc, final String propertyName, final ICellEditorValidator validator) {
super(viewer, dbc);
cellEditor = new CellEditorPrintValidatorErrors((Composite) viewer.getControl());
cellEditor.setValidator(validator);
this.propertyName = propertyName;
}
#Override
protected IObservableValue doCreateCellEditorObservable(final CellEditor cellEditor) {
return SWTObservables.observeText(cellEditor.getControl(), SWT.Modify);
}
#Override
protected IObservableValue doCreateElementObservable(final Object element, final ViewerCell cell) {
return BeansObservables.observeValue(element, propertyName);
}
#Override
protected CellEditor getCellEditor(final Object element) {
return cellEditor;
}
public String getErrorMessage(){
return cellEditor.getErrorMessage();
}
}
I believe it has something to do with the StringEditingSupport class. This class allows to edit the value in each cell of table. But I couldn't figure out a way to "update" the value shown in the GUI. As I understand input (of type WritableList) contains all the information. Here is the add button listener method:
private class AddButtonSelectionListener extends SelectionAdapter {
#Override
public void widgetSelected(final SelectionEvent e) {
String name = nameProperty;
String meaning = dataProperty;
final List<String> names = new ArrayList<String>();
final List<String> meanings = new ArrayList<String>();
for (final Object var : input) {
names.add(((FlowVar) var).getName());
meanings.add(((FlowVar) var).getData());
}
int index = 0;
while (names.contains(name)) {
name = nameProperty + ++index;
}
index = 0;
while (meanings.contains(meaning)) {
meaning = dataProperty + ++index;
}
input.add(new FlowVar(name, valueProperty, meaning));
}
}
So, as I understand, I need to somehow bind the input to the UI (the content of each cell). I did try many attempts like trying to set a listener to the whole table (varTableViewer.addSelectionChangedListener) but none of them worked. Is it possible to suggest a way to solve this kind of issue?
If anything is missing, please let me know and I'll add it.

Wicket CheckBox change visibility of other component

I have a Wicket 7 CheckBox and a hidden DateTextField.
When I click on a CheckBox I want the DateTextField to be appeared and vice versa.
For this reason I have added the DateTextField in a WebMarkUpContainer.
If possible I dont want to use Ajax.
The problem is that the WebMarkUpContainer is always hidden.
In general my code is as follows:
class ResultsPanel extends Panel{
private static final class ResultsPage {
final DateTextField startDate = new DateTextField("startDate", new DateTextFieldConfig().withLanguage("el");
final CheckBox checkBox = new CheckBox("checkBox");
final WebMarkupContainer wmc = new WebMarkupContainer("wmc");
// bla bla bla
public Results(String id, CompoundPropertyModel propertyModel) {
super(id, propertyModel);
add(checkBox);
wmc.setOutputMarkupPlaceholderTag(true);
wmc.add(startDate);
add(wmc.setVisible(false));
}
public ResultsPanel(String id){
super(id);
add(new ResultsPage("resultsPage", new CompoundPropertyModel()));
}
}
if you don't need to trigger any server side code when you click on the checkbox, you can consider to use some simple JavaScript code to hide/show the DateTextField. This code can be attached to the checkbox using a JavaScriptHeaderItem. You can find more details in the user guide.
update
In Wicket 7.x You can try
new CheckBox("id", model) {
protected boolean wantOnSelectionChangedNotifications() {
return true;
}
protected void onSelectionChanged(Boolean newSelection) {
// do something, page will be rerendered;
} };

Working with Java Wicket WiQuery Selectable

Here's a code using wiquery selectable:
SelectableAjaxBehavior selectableAjaxBehavior = new SelectableAjaxBehavior() {
private static final long serialVersionUID = 1L;
#Override
public void onSelection(Component[] components, AjaxRequestTarget ajaxRequestTarget) {
System.out.println("SIZE: " + components.length);
}
};
selectableAjaxBehavior.getSelectableBehavior().setSelectedEvent(new JsScopeUiEvent() {
#Override
protected void execute(JsScopeContext scopeContext) {
scopeContext.append("console.log('ID: ' + ui.selected.id);");
}
});
selectableAjaxBehavior.setFilter(".tooth-image");
add(selectableAjaxBehavior);
I'm trying to use this on images in a class: "tooth-image". When I select some images from the method "onSelection()", I get an empty array of selected components. When triggering select action I see elements' IDs in the browser's console, so it works.
So, maybe someone knows what I have do to stop getting an empty array of selected components ?

How to edit values in wicket table

I created form with editable table and submit button:
#Override
protected void populateItem(final Item<Game> listItem) {
final Game game = listItem.getModelObject();
listItem.setModel(new CompoundPropertyModel<Game>(game));
listItem.add(new TextField("players", Model.of(game.getPlayerResult().getPlayer().getName() + ":"
+ game.getOpponent().getPlayer().getName())));
listItem.add(new TextField("leftSide", Model.of(game.getResult().getLeftSide())));
listItem.add(new TextField("rightSide", Model.of(game.getResult().getRightSide())));
listItem.add(new CheckBox("overtime", Model.of(game.getResult().getOvertime())));
}
now I want to save new value which I insert but when I call:
add(new Button("submit") {
private static final long serialVersionUID = 1L;
#Override
public void onSubmit() {
Iterator<Item<Game>> a = dataView.getItems();
while (a.hasNext()) {
Game game = a.next().getModelObject();
System.out.println(game.getPlayerResult().getPlayer().getName());
}
setResponsePage(new SchedulePage(tournament, table));
}
});
it prints still old value. So how I can get table with new values ?
The way you're doing it, the text fields cannot write back the values into your domain objects.
Learn about models then use the appropriate one:
listItem.add(new TextField("rightSide", new PropertyModel(game, "result.rightSide")));
There are many other options, e.g. safemodel.

Java Wicket AJAX refresh paginated DataView

I have a page that has a list of Hibernate entities that is loaded dynamically on display of the page. The list is used to create a DataView, which is used to display a paginated list of the entries in the list in a container. Each entry in the list has a delete icon on it. When the delete icon is pressed, I lazy delete the entry, reload the list with entities (which will no longer contain the lazy deleted entry), and reload the container, but the entry is still there in the container until I reload the whole page. Why?
public class LogPage extends ProjectPage{
#SpringBean
private LogDao logDao;
#SpringBean
private LogEntryDao logEntryDao;
private List<LogEntry> logEntryList;
private DataView<LogEntry> dataView;
private WebMarkupContainer logEntryListContainer;
public LogPage(PageParameters pp) {
super(pp);
Project activeProject = SciProSession.get().getActiveProject();
Log log = null;
if (activeProject.getLog()==null){
log = new Log(activeProject);
log = logDao.save(log);
}else{
log = activeProject.getLog();
}
logEntryList = logEntryDao.findAll();
Collections.sort(logEntryList);
logEntryListContainer = new WebMarkupContainer("logEntryListContainer");
logEntryListContainer.setOutputMarkupId(true);
dataView = (DataView<LogEntry>) new DataView<LogEntry>("logEntryDataView", new ListDataProvider(logEntryList)) {
private static final long serialVersionUID = 1L;
#Override
protected void populateItem(final Item<LogEntry> item) {
final LogEntry logEntry = item.getModelObject();
item.add(new Label("contents", logEntry.getContents()));
item.add(new Label("creator", logEntry.getCreator().toString()));
AjaxActionIcon deleteIcon = new AjaxActionIcon("deleteIcon", ImageIcon.ICON_DELETE){
private static final long serialVersionUID = 1L;
#Override
protected void onClick(AjaxRequestTarget target) {
LogEntry toBeRemoved = logEntryDao.reLoad(logEntry);
toBeRemoved.setDeleted(true);
logEntryDao.save(toBeRemoved);
logEntryList = logEntryDao.findAll();
target.addComponent(logEntryListContainer);
}
};
item.add(deleteIcon);
}
};
dataView.setItemsPerPage(10);
logEntryListContainer.add(dataView);
logEntryListContainer.add(new PagingNavigator("navigator", dataView));
add(logEntryListContainer);
}
}
You are changing what the variable logEntryList points to, but that does not impact what the new ListDataProvider(logEntryList) sees.
Upon reload, what you could do is
logEntryList.clear().addAll(logEntryDao.findAll()) so that the variable to which the data provider points is updated
provide your own DataProvider implementation
You pass in the list of logEntries upon creation of the DataView. Any changes to the list afterwards will not be reflected. Try wrapping the list in a PropertyModel and provide a getter for it.

Categories

Resources