Apache Wicket AjaxRequestTarget ListView компонент не обновляется или обновляется - PullRequest
0 голосов
/ 30 ноября 2018

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

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

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

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

Проблема:

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

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

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

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

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

Структура страницы / 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 Ответ

0 голосов
/ 30 ноября 2018

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

  • ошибки в журналах сервера
  • ошибки в консоли инструментов разработчика браузера

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

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

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

...