【问题标题】:Validate vaadin combobox custom input (integers only)验证 vaadin 组合框自定义输入(仅限整数)
【发布时间】:2020-07-11 20:37:36
【问题描述】:

我有一个带有显示整数值的组合框的输入表单。我希望用户能够向此组合框添加新的整数值。我需要验证输入是否只有数字(而不是字母) - 如果它不是一个有效的整数,我想显示一条错误消息。

对于文本字段,我很快就明白了——即使输入“错误”输入,我也会收到一条错误消息!但是我找不到与 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");
}

【问题讨论】:

    标签: java vaadin vaadin14


    【解决方案1】:

    我的最终解决方案是使用字符串在前端显示它们并构建一个自定义转换器,在其中我禁用“setGroupingUsed”以阻止 Vaadin 在 UI 中将数千个分隔符插入我的 ID。

    事实证明这比我想象的要容易,我只需要为 UI 使用不同的数据格式,而不是后端 + 自定义转换器。

    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");
    

    【讨论】:

      【解决方案2】:

      所以我想出了一个非常肮脏的 McGyver 解决方案......但它仍然不能 100% 工作。

      主要问题是:

      1. 我必须在 addCustomValueSetListener 中解析(并因此验证)自定义输入
      2. 我无法在 bean-binder 中执行此操作,因为自定义输入是 字符串和 bean-binder 需要一个整数
      3. 使用 withConverter(StringToInteger) 不起作用,因为我仍然想要 能够选择一个整数项目 从下拉菜单中。

      所以我不得不

      • 建立我自己的警告标签
      • 切换时手动重置标签 在表单中显示的对象之间
      • 使用 setInvalid 突出显示错误的输入并在之后重置它
      • 劫持 Validator 以重置 status_label(以解决如果用户在选择错误的下拉菜单后使用下拉菜单 - 标签仍然存在...)的问题。

      我仍然有一个问题,即 binder.hasChanges() 没有将无效输入注册为更改,因为我们事先在解析器中捕获它并且它永远不会到达活页夹。

      也许我明天也会找到解决方案。

          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");
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-06
        • 2020-12-20
        • 2018-03-18
        • 2016-04-14
        相关资源
        最近更新 更多