Компонент Apache Wicket AjaxRequestTarget ListView не обновляется или не обновляется

Я действительно новичок в Apache Wicket (буквально), и я получил задачу, которая требует обновления таблицы (ListView) через ajax после добавления элемента (из модального окна начальной загрузки).

Допустим, у меня есть страница с отображением лабораторных данных (комната) и таблица с перечнем лабораторных приборов.

Чтобы добавить лабораторное устройство, есть кнопка, которая при нажатии... отображает модальное окно (всплывающее окно), где пользователь может выбрать лабораторные устройства из выпадающего списка.

Когда добавляется лабораторное устройство (из всплывающего модального окна), модальное окно будет закрыто / скрыто, а компонент таблицы будет обновляться через ajax.

Проблема:

Код для обновления компонента contentDevices кажется не работает. После добавления лабораторного устройства я вижу, что оно отражено в базе данных. Но по неизвестным причинам контейнер с таблицей, показывающей список лабораторных приборов, не обновляется.

Я хотел бы обновить контейнер / компонент contentDevices после добавления / удаления лабораторного устройства. Компонент contentDevices есть ребенок, который представляет собой таблицу, которая отображает список устройств в лаборатории.

Теперь проблема в том, что мне все еще нужно обновить страницу (обновить браузер), чтобы отразить только что добавленное лабораторное устройство.

Кстати, Device класс не имеет onBeforeRender(), Новый экземпляр этого класса заменит существующий contentDevices,

Уже были дни, но я не могу понять, почему это не освежает. Это действительно легко, если это просто HTML/JS, но я действительно не знаю, с какой Apache Wicket.

Структура page/html выглядит примерно так:

Структура или макет:

<!-- HTML document -->
<Page>
  ...
    <!-- Content section -->
    <div id="content">
      <div id="detailsContainer">
        ...
      </div>
      <div id="devicesContainer">
        ...
        <div id="contentDevices">
          <!-- Other components (ex. table) here that needs to be refreshed after adding/removing device -->
        </div>
        ...
      </div>
      </div>
    </div>
  ...
</Page>

Код:

...

@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
    super.onSubmit(target, form);

    laboratoryService.addDevice(this.laboratoryModel.getObject(), selectedDevice.getLabel(), selectedDevice.getValue());

    // Refresh laboratory model and update the list of laboratory devices from DB
    Laboratory laboratory = laboratoryService.getLaboratory(this.laboratoryModel.getObject().getId());
    this.laboratoryModel = new Model<>(laboratory);

    // Start: refreshing `contentDevices`
    WebMarkupContainer cContent = (WebMarkupContainer) getPage().get("content");
    WebMarkupContainer devicesContainer = (WebMarkupContainer) cContent.get("devicesContainer");
    Component cDevices = devicesContainer.get("contentDevices");
    cDevices.replaceWith(new Device("contentDevices", getMyPageContext(), this.laboratoryModel));

    devicesContainer.addOrReplace(cDevices);
    cContent.addOrReplace(devicesContainer);

    target.add(cContent);
    // End refreshing `contentDevices`

    // Hide bootstrap modal box
    MyUtil.hideBootstrapModalBox(target, "[data-locator=addDeviceModalBox]");

    // showCustomAlert - show success message
    target.appendJavaScript("showCustomAlert('success', 'Added laboratory device.', true);");
}

...

Класс устройства:

public class Device extends AbstractMyPagePanel {

    private static final long serialVersionUID = 1L;

    @Autowired
    private LaboratoryService laboratoryService;

    private IModel<Laboratory> laboratoryModel;


    public Device(String id, MyPageContext myPageContext, IModel<Laboratory> laboratoryModel) {
        // `laboratoryModel` is passed until most parent class which is `org.apache.wicket.markup.html.panel.Panel`
        super(id, myPageContext, laboratoryModel);

        this.laboratoryModel = laboratoryModel;

        add(createAddDeviceButton());
        add(new AddDeviceModalBox("addDeviceModalBox", myPageContext, this.laboratoryModel));
        add(createRowsContainer());
        setOutputMarkupId(true);
    }

    private Component createAddDeviceButton() {
        return new WebMarkupContainer("addDeviceButton") {
            private static final long serialVersionUID = 1L;
            @Override
            protected void onConfigure() {
                super.onConfigure();
                setVisible(isAdmin());
            }
        };
    }

    private Component createRowsContainer() {
        WebMarkupContainer result = new WebMarkupContainer("rowsContainer") {
            private static final long serialVersionUID = 1L;
            @Override
            protected void onConfigure() {
                super.onConfigure();
                setVisible(CollectionUtils.isNotEmpty(this.laboratoryModel.getObject().getRoomDevices()));
                setOutputMarkupPlaceholderTag(true);
            }
        };

        // This part here is OK, laboratory model and devices are updated
        System.out.println("\n");
        System.out.println("CREATE-ROW-CONTAINER");
        System.out.println("---------------------------------------------");
        System.out.println("[device-count]: " + this.laboratoryModel.getObject().getRoomDevices().size());
        System.out.println("---------------------------------------------");
        System.out.println("\n");

        System.out.println("\n");
        System.out.println("LABORATORY-DEVICES");
        System.out.println("---------------------------------------------");
        for (LaboratoryDevice device : this.laboratoryModel.getObject().getRoomDevices()) {
            System.out.println("[device]: " + device.getName());
        }
        System.out.println("---------------------------------------------");
        System.out.println("\n");

        // This part here is not OK, `populateItem()` is not called
        // `rows.children` is null, but `rows.data.transientModelObject` is updated and contains the latest added laboratory device
        // Same goes when `add` is used instead of `addOrReplace`, the issue is still there
        result.addOrReplace(new ListView<LaboratoryDevice>("rows", this.laboratoryModel.getObject().getRoomDevices()) {
            private static final long serialVersionUID = 1L;
            @Override
            protected void populateItem(ListItem<LaboratoryDevice> item) {
                LaboratoryDevice device = item.getModelObject();
                item.add(new Label("name", device.getName()));
                item.add(new Label("sn", device.getSn()));
                item.add(new WebMarkupContainer("removeButton").setVisible(isAdmin()));
                item.add(new RemoveLaboratoryDeviceModalBox("removeLaboratoryDeviceModalBox",
                                                  getMyPageContext(), item.getModel()));
            }
        });
        return result;
    }

}

Я знаю, что это очень просто, но я не смог найти ничего, что действительно работает в сети:(

Спасибо!

1 ответ

Вы должны проверить, есть ли какие-либо ошибки:

  • ошибки в логах сервера
  • ошибки в браузере Dev Tools Console

Я предполагаю, что в Dev Tools есть ошибка JS, говорящая, что Wicket не может найти элемент HTML с идентификатором contentXYZ, Если это так, то обязательно позвоните cContent.setOutputMarkupId(true) где cContent создается в конструкторе страницы.

Вы не должны cDevices.setOutputMarkupId(true) потому что ты никогда не добавляешь cDevices к target,

И зовет setOutputMarkupId(true) в onXYZ(AjaxRequestTarget) в большинстве случаев это слишком поздно, потому что вся страница уже отрисована, а компонент / элемент должен визуализировать id атрибут, который будет использоваться позже, когда ответ Ajax попытается найти старый элемент HTML и заменить его новым (созданным или обновленным в onXYZ(AjaxRequestTarget),

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