Здравствуйте!
Только что нашел решение (и успешно внедрил его в свой проект) старой (для меня) проблемы.
Суть заключалась в следующем.
Пользователь переводил таблицу в режим редактирования и менял в ней значения.
При этом, каждое изменение тут же записывалось в БД и сохранялось в ней.
Так же это значение сохранялось и на экране пользователя, в его таблице.
Но!
Как только пользователь переходил (к примеру в таблице 3 строчки) сначала от первой ко второй, от второй к третьей и затем обратно к первой, но значения менял уже в другой ячейке, данные в первой строчке первой редактируемой ячейке визуально оставались измененными, а в реальности, в представлении модели таблицы, значение в выбранной строке были все теми же. В результате, после выхода из режима редактирования, данные в ячейках, не сохранялись.
А точнее они сначала обновлялись, но затем обновлялись вновь на старые значения.
Мне удалось найти тикет, который описывает данный баг http://dev.vaadin.com/ticket/10993
Приведу скрины таблицы от исходных данных, до момента редактирования и его последовательности и получившийся результат.
Как вы видите, данные в первых двух столбцах не изменились, хотя в процессе они менялись, но при выборе первой строки, данные для объекта подтягивались не обновленные, а старые, то есть значения "1". В результате только данные из последнего столбца сохранялись в БД нужным образом.
Решение нашлось на форуме Vaadin, там же я нашел и ссылку на тикет с багом.
Я сделал просто - создал отдельный класс и стал вызывать его при каждом создании таблицы.
Привожу код класса:
import com.vaadin.data.Container;
import com.vaadin.data.Container.ItemSetChangeEvent;
import com.vaadin.ui.Table;
import java.util.Collection;
import java.util.Collections;
/**
*
* @author nix
*/
public class UpdateTableSelectionOnItemSetChange implements Container.ItemSetChangeListener {
private Table table;
public UpdateTableSelectionOnItemSetChange(final Table table) {
super();
this.table = table;
}
@Override
public void containerItemSetChange(ItemSetChangeEvent event) {
final Collection<Object> itemIds = (Collection<Object>) table.getContainerDataSource().getItemIds();
if (itemIds.isEmpty()) {
// a previously filled table is now empty ==> remove its value since its selection is outdated this also
// updates dependent forms via a resulting value change event
table.setValue(null);
} else {
final Object tableVal = table.getValue();
if (tableVal instanceof Collection && tableVal != null && !((Collection) tableVal).isEmpty()) {
final Object selectedItemId = ((Collection<Object>) tableVal).iterator().next();
// FIXME: needs to be adapted for multiselect tables
for (final Object itemId : itemIds) {
if (itemId.equals(selectedItemId) && itemId != selectedItemId) {
table.setValue(null); // otherwise the next set value will be discarded since
// oldVal.equals(newVal)
table.setValue(Collections.singleton(itemId));
break;
}
}
}
}
}
}
Можно найти более элегантное применение, если у вас оно есть - поделитесь, лишним не будет. Я же пока оставлю так. Главное, что данные теперь всегда "свежие" :)
Только что нашел решение (и успешно внедрил его в свой проект) старой (для меня) проблемы.
Суть заключалась в следующем.
Пользователь переводил таблицу в режим редактирования и менял в ней значения.
При этом, каждое изменение тут же записывалось в БД и сохранялось в ней.
Так же это значение сохранялось и на экране пользователя, в его таблице.
Но!
Как только пользователь переходил (к примеру в таблице 3 строчки) сначала от первой ко второй, от второй к третьей и затем обратно к первой, но значения менял уже в другой ячейке, данные в первой строчке первой редактируемой ячейке визуально оставались измененными, а в реальности, в представлении модели таблицы, значение в выбранной строке были все теми же. В результате, после выхода из режима редактирования, данные в ячейках, не сохранялись.
А точнее они сначала обновлялись, но затем обновлялись вновь на старые значения.
Мне удалось найти тикет, который описывает данный баг http://dev.vaadin.com/ticket/10993
Приведу скрины таблицы от исходных данных, до момента редактирования и его последовательности и получившийся результат.
Как вы видите, данные в первых двух столбцах не изменились, хотя в процессе они менялись, но при выборе первой строки, данные для объекта подтягивались не обновленные, а старые, то есть значения "1". В результате только данные из последнего столбца сохранялись в БД нужным образом.
Решение нашлось на форуме Vaadin, там же я нашел и ссылку на тикет с багом.
Я сделал просто - создал отдельный класс и стал вызывать его при каждом создании таблицы.
Привожу код класса:
import com.vaadin.data.Container;
import com.vaadin.data.Container.ItemSetChangeEvent;
import com.vaadin.ui.Table;
import java.util.Collection;
import java.util.Collections;
/**
*
* @author nix
*/
public class UpdateTableSelectionOnItemSetChange implements Container.ItemSetChangeListener {
private Table table;
public UpdateTableSelectionOnItemSetChange(final Table table) {
super();
this.table = table;
}
@Override
public void containerItemSetChange(ItemSetChangeEvent event) {
final Collection<Object> itemIds = (Collection<Object>) table.getContainerDataSource().getItemIds();
if (itemIds.isEmpty()) {
// a previously filled table is now empty ==> remove its value since its selection is outdated this also
// updates dependent forms via a resulting value change event
table.setValue(null);
} else {
final Object tableVal = table.getValue();
if (tableVal instanceof Collection && tableVal != null && !((Collection) tableVal).isEmpty()) {
final Object selectedItemId = ((Collection<Object>) tableVal).iterator().next();
// FIXME: needs to be adapted for multiselect tables
for (final Object itemId : itemIds) {
if (itemId.equals(selectedItemId) && itemId != selectedItemId) {
table.setValue(null); // otherwise the next set value will be discarded since
// oldVal.equals(newVal)
table.setValue(Collections.singleton(itemId));
break;
}
}
}
}
}
}
Теперь в класс где у нас создается табличка просто добавляем создание экземпляра этого класса. Конечно, лучше его указывать сразу в списке переменных и затем вызывать только конструктор.
UpdateTableSelectionOnItemSetChange onItemSetChange = new UpdateTableSelectionOnItemSetChange(table);
Можно найти более элегантное применение, если у вас оно есть - поделитесь, лишним не будет. Я же пока оставлю так. Главное, что данные теперь всегда "свежие" :)