Как получить доступ к @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.

Другие вопросы по тегам