Vaadin7 динамически заполняет комбинированный список из Rest API - PullRequest
1 голос
/ 02 апреля 2020

Я хотел бы динамически заполнить комбинированный список из Vaadin7, используя API отдыха. API возвращает много значений, если они не отфильтрованы.

Это базовая c идея, которая у меня есть. Я знаю, что версия Vaadin содержит более эффективные способы привязки данных, но мне нужно использовать это устаревшую устаревшую систему.

Моя основная проблема заключается в том, что событие не запускается при вводе новых значений, а также я не уверен, как получить текущее значение в поле со списком, поэтому я могу отправить его в качестве фильтра в API

Вот код

@SpringUI
public class MainView extends UI {

  @Autowired
  private NameService nameService;

  private ComboBox comboBox;

  @Override
  protected void init(VaadinRequest request) {
    VerticalLayout verticalLayout = new VerticalLayout();

    comboBox = new ComboBox();
    comboBox.setContainerDataSource(getDataSource());
    comboBox.setItemCaptionMode(ItemCaptionMode.PROPERTY);
    comboBox.setItemCaptionPropertyId("name");
    comboBox.setImmediate(true);

    comboBox.addValueChangeListener(event -> {
          // When I manually enter a property I want to go to the server
          // Rest API and get a new List of names
          String filter = event.getProperty().toString();
          comboBox.setContainerDataSource(getDataSourceWithFilter(filter));
        }
    );

    verticalLayout.addComponent(comboBox);
    setContent(verticalLayout);
  }

  // Get 20 names with a filter
  private BeanContainer<String, Name> getDataSourceWithFilter(String filter) {
    BeanContainer<String, Name> container = new BeanContainer<>(Name.class);

    container.setBeanIdResolver(Name::getId);
    // this list comes from a webservice API
    List<Name> names = nameService.fetch(filter, 0, 20).collect(Collectors.toList());
    container.addAll(names);

    return container;
  }

  // Get 20 (default) names without filtering
  private BeanContainer<String, Name> getDataSource() {
    return getDataSourceWithFilter("");
  }
}

1 Ответ

1 голос
/ 03 апреля 2020

Я нашел решение, создав свой собственный Combobox и переопределив метод changeVariables . Спасибо всем, кто указал мне правильное направление.

Так это выглядит так:

public class FilteringComboBox extends ComboBox {

  @Override
  public void changeVariables(Object source, Map<String, Object> variables) {
    if (variables.containsKey("filter")) {
      final String text = variables.get("filter").toString();
      fireEvent(new TextChangeEvent(this) {

        @Override
        public String getText() {
          return text;
        }

        @Override
        public int getCursorPosition() {
          return text.length();
        }
      });
    }
    super.changeVariables(source, variables);
  }

  public void addTextChangeListener(TextChangeListener listener) {
    addListener(TextChangeListener.EVENT_ID, TextChangeEvent.class, listener, TextChangeListener.EVENT_METHOD);
  }

  public void removeTextChangeListener(TextChangeListener listener) {
    removeListener(TextChangeListener.EVENT_ID, TextChangeEvent.class, listener);
  }
}

А потом я использовал его в основном интерфейсе следующим образом:

@SpringUI
public class MainView extends UI {

  @Autowired
  private NameService nameService;

  private FilteringComboBox comboBox;

  @Override
  protected void init(VaadinRequest request) {
    VerticalLayout verticalLayout = new VerticalLayout();

    comboBox = new FilteringComboBox();
    comboBox.setContainerDataSource(getDataSource(""));
    comboBox.setItemCaptionMode(ItemCaptionMode.PROPERTY);
    comboBox.setItemCaptionPropertyId("name");
    comboBox.setImmediate(true);

    comboBox.addTextChangeListener(event -> {
          String filter = event.getText();
          comboBox.setContainerDataSource(getDataSource(filter));
        }
    );

    verticalLayout.addComponent(comboBox);
    setContent(verticalLayout);
  }

  private BeanContainer<String, Name> getDataSource(String filter) {
    BeanContainer<String, Name> container = new BeanContainer<>(Name.class);

    container.setBeanIdResolver(Name::getId);

    List<Name> names = nameService.fetch(filter, 0, 20).collect(Collectors.toList());
    container.addAll(names);

    return container;
  }
}
...