Как получить доступ к @EventData в @DomEvent в компоненте Vaadin
Я создал компонент Vaadin Flow v22, обертывающий веб-компонент UI5 MultiComboBox:
@Tag("ui5-multi-combobox")
@NpmPackage(value = "@ui5/webcomponents", version = "^1.1.2")
@JsModule("@ui5/webcomponents/dist/MultiComboBox.js")
@JsModule("@ui5/webcomponents/dist/features/InputElementsFormSupport.js")
public class Ui5MultiComboBox extends Component implements HasComponents, HasLabel, HasSize {
…
public void setPlaceholder(String placeholder) {
this.getElement().setProperty("placeholder", placeholder);
}
…
@DomEvent("selection-change")
public static class SelectionChangeEvent extends ComponentEvent<Ui5MultiComboBox> {
public SelectionChangeEvent(Ui5MultiComboBox source, boolean fromClient,
@EventData("element.placeholder") String placeholder,
@EventData("event.bubbles") boolean bubbles,
@EventData("event.items") JsonArray itemsa) {
super(source, fromClient);
LOGGER.info("Ui5MultiComboBoxSelectionChangeEvent: placeholder=" + placeholder);
LOGGER.info("Ui5MultiComboBoxSelectionChangeEvent: bubbles=" + bubbles);
LOGGER.info("Ui5MultiComboBoxSelectionChangeEvent: itemsa=" + itemsa);
}
}
…
public Registration addSelectionChangeListener(ComponentEventListener<SelectionChangeEvent> listener) {
return addListener(SelectionChangeEvent.class, listener);
}
}
Затем я использую компонент Vaadin в своем представлении Vaadin:
…
Ui5MultiComboBox multiCombo1 = new Ui5MultiComboBox();
multiCombo1.setPlaceholder("Enter or pick items");
multiCombo1.addSelectionChangeListener(e -> {
LOGGER.info("View: Selection Changed Listener ...");
});
getContent().add(multiCombo1);
// add items:
for (ItemData d : data) {
Ui5MultiComboBoxItem multiComboItem = new Ui5MultiComboBoxItem();
multiComboItem.setText(d.text);
multiComboItem.setSelected(d.selected);
multiCombo1.add(multiComboItem);
}
Я запускаю свое приложение (в Crome), и оно отображается так, как ожидалось. Когда я удаляю один из
Ui5MultiComboBoxItem
, мой Listener срабатывает, как и ожидалось.
Проблема в том, что Listener не получает доступа к элементам JsonArray @EventData("event.items").
Консоль показывает null для этого
itemsa
переменная, в то время как доступ к более простым @EventData, таким как «element.placeholder» или «event.bubbles», отлично работает:
Ui5MultiComboBoxSelectionChangeEvent: placeholder=Enter or pick items
Ui5MultiComboBoxSelectionChangeEvent: bubbles=true
Ui5MultiComboBoxSelectionChangeEvent: itemsa=null
View: Selection Changed Listener ...
Я также использовал:
@EventData("event.detail") JsonArray itemsa
@EventData("event.detail.items") JsonArray itemsa
@EventData("event.detail") JsonObject itemsa
@EventData("event.detail.items") JsonObject itemsa
@EventData("event.detail") String itemsa
@EventData("event.detail.items") String itemsa
@EventData("event.detail") Object itemsa
@EventData("event.detail.items") Object itemsa
но все это вызывает ошибку в консоли Chrome:
(String) : Message JsonObject contained a dom node reference which should not be sent to the server and can cause a cyclic dependecy.
Опечатка в "
dependecy
" может дать подсказку, кто выдает это сообщение об ошибке.
Вот описание веб-компонента UI5: MultiComboBox
Любая помощь высоко ценится!
1 ответ
Вам нужно подробно знать, как веб-компонент, который вы интегрируете, реализовал эту деталь. Я беру один из моих собственных проектов в качестве примера здесь. Итак, допустим, у меня есть веб-компонент
tab-sheet
, там где я стреляю кастом даже называется
tab-changed.
Мне нужно, чтобы некоторые метаданные были доставлены на сервер в событии, поэтому я составляю объект JSON.
details
с парой свойств.
selectedChanged(e: CustomEvent) {
const page = e.detail.value;
const tab = this.getTab(page);
this._doSelectTab(page);
const details : JSON = <JSON><unknown>{
"index": page,
"caption": this.getTabCaption(tab),
"tab": tab
}
const event = new CustomEvent('tab-changed', {
detail: details,
composed: true,
cancelable: true,
bubbles: true
});
this.dispatchEvent(event);
}
Полная реализация компонента находится здесь: https://github.com/TatuLund/TabSheet/blob/master/src/main/resources/META-INF/resources/frontend/tab-sheet.ts .
Теперь я хочу наблюдать за этим событием в классе Java, который является представлением компонента на стороне сервера.
я использую
@DomEvent
для этого и в конструкторе класса событий я расшифровываю JSON, используя
@EventData("event.detail")
, который теперь содержит объект JSON, который я составил.
@DomEvent("tab-changed")
public static class TabChangedEvent<R extends TabSheet> extends ComponentEvent<TabSheet> {
private int index;
private TabSheet source;
private String caption;
private String tab;
public TabChangedEvent(TabSheet source, boolean fromClient, @EventData("event.detail") JsonObject details) {
super(source, fromClient);
this.index = (int) details.getNumber("index");
this.tab = details.getString("tab");
this.caption = details.getString("caption");
this.source = source;
}
...
}
Полный код находится здесь: https://github.com/TatuLund/TabSheet/blob/master/src/main/java/org/vaadin/addons/tatu/TabSheet.java.