Проверьте пользовательский ввод vaadin combobox (только целые числа) - PullRequest
0 голосов
/ 31 марта 2020

У меня есть форма ввода с комбинированным списком, который отображает целочисленные значения. Я хочу, чтобы пользователь мог добавлять новые целочисленные значения в этот список. Мне нужно проверить, являются ли ввод только числа (а не буквы) - если это не действительное целое число, я хочу отобразить сообщение об ошибке.

Для текстовых полей я понял это быстро - я получаю сообщение об ошибке даже при вводе «неправильного» ввода! Но я не могу найти решение для комбинированного списка в сочетании с addCustomValueSetListener.

Я использую Vaadin 14.1.21 и Java JDK + JRE 1.8.

Прямо сейчас, если я введу пользовательское значение с буквами, я не получаю сообщение об ошибке, отображаемое под полем, и оно просто молча игнорирует входное значение, когда я хочу «сохранить» его / сохранить в базе данных.

public class MyForm extends Div {


    private TextField tf;
    tf =new TextField("TF");
    tf.setWidth("100%");
    tf.setRequired(true);
    tf.addThemeVariants(TextFieldVariant.LUMO_ALIGN_RIGHT);
    tf.setValueChangeMode(ValueChangeMode.EAGER);

    private ComboBox<Integer> combo_int;
    combo_int= new ComboBox<>();
    combo_int.setItems(114, 12383, 65432189);
    combo_int.setLabel("Some ID");
    combo_int.addCustomValueSetListener(
            event -> combo_int.setValue(Integer.parseInt(event.getDetail()))
            // since I need to parse new values here, I cannot use a validator upon binding
    );

    binder = new BeanValidationBinder<>(MyData.class);
    binder.forField(tf)
            .withNullRepresentation("")
            .withConverter(new StringToIntegerConverter("needs to be integer!"))
            .bind("tf_data_integer");

    binder.forField(combo_int)
            .bind("integer_data");
}

Ответы [ 2 ]

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

Мое окончательное решение состояло в том, чтобы использовать строки для отображения их во внешнем интерфейсе и создать собственный конвертер, в котором я отключаю «setGroupingUsed», чтобы запретить Vaadin вставлять тысячи разделителей в мои идентификаторы в пользовательском интерфейсе.

Повороты В итоге это оказалось проще, чем я думал, мне просто пришлось использовать другой формат данных для пользовательского интерфейса, нежели для внутреннего интерфейса + пользовательский конвертер.

private static class Id_StringToInteger_Converter extends StringToIntegerConverter {

    public Id_StringToInteger_Converter() {
        super("Input has to be an Integer!");
    }

    @Override
    protected NumberFormat getFormat(Locale locale) {
        final NumberFormat format = super.getFormat(locale);
        format.setGroupingUsed(false); // disable thousands-seperator!
        return format;
    }
}

combo_int= new ComboBox<>();
combo_int.setItems("6583212", "114514", "879278");
combo_int.setLabel("Some ID");
combo_int.addCustomValueSetListener(event -> combo_int.setValue(event.getDetail()));


binder.forField(kreditoren_id)
      .withNullRepresentation("")
      .withConverter(new Id_StringToInteger_Converter())
      .bind("kreditoren_id");
0 голосов
/ 31 марта 2020

Итак, я разобрался с очень грязным решением McGyver ... но оно все равно не работает на 100%.

Основная проблема заключается в том, что:

  1. Я должен проанализировать (и, следовательно, проверить) пользовательский ввод в addCustomValueSetListener
  2. Я не могу сделать это в bean-binder поскольку пользовательский ввод представляет собой String, а связыватель bean-компонентов ожидает целое число
  3. Использование withConverter (StringToInteger) не работает, так как я все еще хочу иметь возможность выбрать элемент Integer из выпадающего меню.

Так что мне пришлось

  • создать свою собственную метку предупреждения
  • сбросить метку вручную при переключении между объектами, которые отображаются в форме
  • используйте setInvalid, чтобы выделить неправильный ввод и сбросить его после
  • . Снова нажмите Validator, чтобы сбросить метку status_label (чтобы исправить проблему с меткой, оставшейся, если пользователь использовал выпадающее меню после выбора неправильной - метка осталась ...)

У меня все еще есть проблема в том, что binder.hasChanges () не регистрирует неверный ввод как изменение, так как мы заранее его перехватываем в p arser, и он никогда не доберется до переплета.

Возможно, завтра я тоже найду решение для этого.

    public class MyForm extends Div {

    private Label status_label = new Label();

    private TextField tf;
    tf =new TextField("TF");
    tf.setWidth("100%");
    tf.setRequired(true);
    tf.addThemeVariants(TextFieldVariant.LUMO_ALIGN_RIGHT);
    tf.setValueChangeMode(ValueChangeMode.EAGER);

    private ComboBox<Integer> combo_int;
    combo_int= new ComboBox<>();
    combo_int.setItems(114, 12383, 65432189);
    combo_int.setLabel("Some ID");
    combo_int.addCustomValueSetListener((event -> {            
            if (isInteger(event.getDetail())){
                status_label.setText(""); // reset on success  
                warengruppen_id.setValue(Integer.parseInt(event.getDetail()));
                warengruppen_id.setInvalid(false);
            } else {
                status_label.setText("Custom Format-Error!"); // set to error
                status_label.getStyle().set("color", "red");
                combo_int.setInvalid(true); // red background coloring
            }
        }
      );

    binder = new BeanValidationBinder<>(MyData.class);
    binder.forField(tf)
            .withNullRepresentation("")
            .withConverter(new StringToIntegerConverter("needs to be integer!"))
            .bind("tf_data_integer");

    binder.forField(combo_int).
             withValidator(event -> {
                    // we highjack the Validator to reset the field on correct input
                    status_label.setText("");
                    return true; // never raise the validator message
                }, "")
            .withNullRepresentation(null)
            .bind("integer_data");
    }
...