【问题标题】:Checkbox form validation复选框表单验证
【发布时间】:2018-11-26 11:16:19
【问题描述】:

如何验证 Flutter Form 中的复选框?其他所有验证工作正常,但复选框不显示错误。 这是我的代码:

FormField(
  validator: (value) {
    if (value == false) {
      return 'Required.';
    }
  },
  builder: (FormFieldState<dynamic> field) {
    return CheckboxListTile(
      value: checkboxValue,
      onChanged: (val) {
        if (checkboxValue == false) {
          setState(() {
            checkboxValue = true;
          });
        } else if (checkboxValue == true) {
          setState(() {
            checkboxValue = false;
          });
        }
      },
      title: new Text(
        'I agree.',
        style: TextStyle(fontSize: 14.0),
      ),
      controlAffinity: ListTileControlAffinity.leading,
      activeColor: Colors.green,
    );
  },
),

【问题讨论】:

  • 您确定这是您要使用的复选框吗?复选框允许用户将其值输入为真或假,因此如果它是“空白”,则不会出现错误,因为“空白”复选框是有效输入。
  • @SnakeyHips 是的,我希望使用“我同意条款和条件”复选框。

标签: flutter


【解决方案1】:

解决这个问题的更简洁的方法是创建一个扩展 FormField&lt;bool&gt; 的类

我是这样实现的:

class CheckboxFormField extends FormField<bool> {
  CheckboxFormField(
      {Widget title,
      FormFieldSetter<bool> onSaved,
      FormFieldValidator<bool> validator,
      bool initialValue = false,
      bool autovalidate = false})
      : super(
            onSaved: onSaved,
            validator: validator,
            initialValue: initialValue,
            builder: (FormFieldState<bool> state) {
              return CheckboxListTile(
                dense: state.hasError,
                title: title,
                value: state.value,
                onChanged: state.didChange,
                subtitle: state.hasError
                    ? Builder(
                        builder: (BuildContext context) =>  Text(
                          state.errorText,
                          style: TextStyle(color: Theme.of(context).errorColor),
                        ),
                      )
                    : null,
                controlAffinity: ListTileControlAffinity.leading,
              );
            });
}

【讨论】:

  • 我也认为这是一个更干净的解决方案,与其他表单字段小部件更一致。我只是添加一个 6px 的顶部填充并将字幕对齐在中心。
【解决方案2】:

如果您想将复选框直接放在表单小部件树中,您可以使用下面提供的解决方案和 FormField 小部件。我没有使用 ListTile,而是使用了行和列,因为我的表单需要不同的布局。

FormField<bool>(
  builder: (state) {
    return Column(
      children: <Widget>[
        Row(
          children: <Widget>[
            Checkbox(
              value: checkboxValue,
              onChanged: (value) {
                setState(() {
//save checkbox value to variable that store terms and notify form that state changed
                  checkboxValue = value;
                  state.didChange(value);
                });
              }),
            Text('I accept terms'),
          ],
        ),
//display error in matching theme
        Text(
          state.errorText ?? '',
          style: TextStyle(
            color: Theme.of(context).errorColor,
          ),
        )
      ],
    );
  },
//output from validation will be displayed in state.errorText (above)
  validator: (value) {
    if (!checkboxValue) {
      return 'You need to accept terms';
    } else {
      return null;
    }
  },
),

【讨论】:

    【解决方案3】:

    你可以试试这样的:

    CheckboxListTile(
      value: checkboxValue,
      onChanged: (val) {
        setState(() => checkboxValue = val
      },
      subtitle: !checkboxValue
          ? Text(
              'Required.',
              style: TextStyle(color: Colors.red),
            )
          : null,
      title: new Text(
        'I agree.',
        style: TextStyle(fontSize: 14.0),
      ),
      controlAffinity: ListTileControlAffinity.leading,
      activeColor: Colors.green,
    );
    

    【讨论】:

      【解决方案4】:

      上面的答案是正确的,但是,如果你想显示一个更符合 TextFormField 小部件错误消息的默认布局的错误消息,那么将 Text 小部件包装在一个 Padding 小部件中,并赋予它十六进制颜色#e53935.

      注意:您可能需要调整左侧填充以适应 CheckboxListTile 小部件也包含在 Padding 小部件中。

      检查下面的代码:

          bool _termsChecked = false;
          CheckboxListTile(
                    activeColor: Theme.of(context).accentColor,
                    title: Text('I agree to'),
                    value: _termsChecked,
                    onChanged: (bool value) => setState(() => _termsChecked = value),
                    subtitle: !_termsChecked
                      ? Padding(
                          padding: EdgeInsets.fromLTRB(12.0, 0, 0, 0), 
                          child: Text('Required field', style: TextStyle(color: Color(0xFFe53935), fontSize: 12),),)
                      : null,
                  ),
      

      【讨论】:

      • 这是我想出来的,哈哈,除了我使用了更容易记住的 color.red
      猜你喜欢
      • 2017-05-04
      • 2011-10-24
      • 1970-01-01
      • 1970-01-01
      • 2012-10-01
      • 2021-11-07
      • 2020-08-11
      • 2018-02-19
      • 2010-10-01
      相关资源
      最近更新 更多