Привет!
У меня есть GroupTable, одна из колонок которой генерируется при помощи метода .addGeneratedColumn();
Значения этой колонки задаются из коллекции, которую я могу обновлять при помощи EventListener.
Вопрос в следующем: могу ли я обновлять GroupTable (или только генерируемую колонку) без перезагрузки всей страницы динамически?
GroupTable наследует Table
. Там есть метод repaint()
Привет! Спасибо за ответ. Я думал в этом направлении , попробую обьяснить ход своих действий:
У меня есть вот такая таблица:
Колонка “Непрочитанные” генерируется здесь при помощи .addGeneratedColumn(). Значения для этой колонки лежат в коллекции countersDc. При изменениях этой коллекции при нажатии на любой из элементов группировки (+) значения непрочитанных сообщений меняются правильно на переданные в коллекцию. Я пытаюсь на данный момент сделать так, чтоб таблица перерисовывалась на экране без какого-либо вмешательства пользователя.
Я написал метод для обновления по event изменения этой коллекции:
При использовании этого метода я ловлю exception io.jmix.ui.executor.IllegalConcurrentAccessException: UI Shared state was accessed from a background thread
Далее я решил использовать uiAccessor:
Метод отрабатывает успешно, однако в UI сама таблица не обновляется , а появляется лишь бесконечный длящийся прогрессбар. При обновлении страницы значения в необходимых полях обновляются верно.
Буду благодарен за любую помощь
Весь код класса:
Спойлер
@Slf4j
@UiController(“Chat.browse”)
@UiDescriptor(“chat-browse.xml”)
@LookupComponent(“chatTable”)
public class CompanyChat extends StandardLookup {
@Autowired private GroupTable chatTable;
@Autowired private CollectionLoader companiesDl;
@Autowired private UiComponents uiComponents;
@Autowired private BrowserFrame chatFrame;
@Autowired private CurrentAuthentication currentAuthentication;
@Autowired private Messages messages;
@Autowired private FirestoreService firestoreService;
@Autowired private ChatUrlService chatUrlService;
@Autowired private CollectionContainer countersDc;
@Autowired private BackgroundWorker backgroundWorker;
private UIAccessor uiAccessor;
@Subscribe
public void onInit(InitEvent event) {
uiAccessor = backgroundWorker.getUIAccessor();
getCollectionChangeEvent();
countersDc.setItems(firestoreService.getAllCounters());
addGeneratedUnreadMessageColumn();
}
@Subscribe
public void onBeforeShow(BeforeShowEvent event) {
UserDetails user = currentAuthentication.getUser();
if (user instanceof Accountant) {
companiesDl.setParameter("accountant", user);
}
companiesDl.load();
chatTable.expandAll();
}
private void addGeneratedUnreadMessageColumn() {
chatTable.addGeneratedColumn(messages.getMessage("kz.advance.onlinebuhgalteria.screen.company.chat/unread"), entity -> {
var accountantCounter = countersDc.getItems()
.stream()
.filter(o -> o.getId()
.equals(entity.getUser()
.getId()
.toString()))
.map(o -> o.getCounters()
.get("accountantCounter"))
.map(o -> o == null ? 0L : o)
.findFirst();
var label = uiComponents.create(Label.TYPE_LONG);
label.setValue(accountantCounter.orElse(0L));
return label;
});
}
private void getChatFrame(CompanyUser user, UUID companyId) {
var chatUrl = chatUrlService.getUrl(user, companyId);
chatFrame.setSource(UrlResource.class)
.setUrl(chatUrl);
}
@Subscribe("chatTable")
public void onChatTableSelection(Table.SelectionEvent<CompanyUserLink> event) {
var iterator = event.getSelected()
.iterator();
if (iterator.hasNext()) {
chatFrame.setVisible(true);
var companyUser = iterator.next();
getChatFrame(companyUser.getUser(), companyUser.getCompany()
.getId());
} else {
chatFrame.setVisible(false);
}
}
@Subscribe(id = "countersDc", target = Target.DATA_CONTAINER)
public void onCountersDcCollectionChange(CollectionContainer.CollectionChangeEvent<Counter> event) {
uiAccessor.access(() -> {
chatTable.repaint();
});
}
private void getCollectionChangeEvent() {
var firestore = FirestoreClient.getFirestore();
var countersCollection = firestore.collection("counters");
countersCollection.addSnapshotListener((value, error) -> {
countersDc.setItems(value.getDocuments()
.stream()
.map(o -> o.toObject(Counter.class))
.collect(Collectors.toList()));
});
}
}
Вы не пробовали uiAccessor.accessSynchronously
? Сложно сказать почему прогрессбар не заканчивается. Мб где-то лок процесса произошел…
Возможно uiAccessor.access
лучше перенести в addSnapshotListener
Спасибо за ответ!
Перенес uiAccessor.access
в addSnapshotListener
ловлю com.vaadin.v7.ui.Table$CacheUpdateException: Error during Table cache update. Additional causes not shown
. В cause - java.lang.IllegalStateException: Authentication is not set. Use SystemAuthenticator in non-user requests like schedulers or asynchronous calls.
Использую SystemAuthenticator
:
Уже не получаю никаких экспешнов, но получаю бесконечный прогрессбар, таблица не обновляется. Не работают оба варианта, ни .access
, ни .accessSynchronously
Сработал такой вариант. Огромное спасибо за помощь!