【问题标题】:How to pass a validator to the `TextFormField' in Flutter?如何将验证器传递给 Flutter 中的“TextFormField”?
【发布时间】:2019-08-28 03:32:00
【问题描述】:

我在我的颤振应用程序中为我的表单动态生成文本字段。请检查以下代码

Widget _buildInputFields(
    String label,
    TextEditingController textController,
    TextInputType textInputType,
    IconData icon,
    Color iconColor,
  ) {
    return Container(
        margin: EdgeInsets.only(left: 20, bottom: 20),
        child: Container(
          padding: EdgeInsets.only(right: 20),
          child: Row(
            children: <Widget>[
              Flexible(
                child: TextFormField(
                  controller: textController,
                  validator: (value) {
                    if (value.isEmpty) {
                      return 'Please enter some text';
                    }
                  },
                  style: new TextStyle(color: Colors.white),
                  keyboardType: textInputType,
                  decoration: InputDecoration(
                      labelText: label,
                      fillColor: Colors.white,
                      labelStyle: TextStyle(
                          color: Colors.white, fontWeight: FontWeight.w600),
                      enabledBorder: OutlineInputBorder(
                        borderSide:
                            const BorderSide(color: Colors.white30, width: 2.0),
                        borderRadius: BorderRadius.circular(25.0),
                      ),
                      suffixIcon: IconButton(
                        icon: Icon(icon, color: iconColor),
                        onPressed: () {},
                      )),
                ),
              ),
            ],
          ),
        ));
  }

上面的方法返回一个TextFormField我需要的样式,所以我不必重新编码数百次。我只是调用该方法,我得到一个新的TextFormField

无论如何,我需要进行表单验证,每个字段都有不同的验证。在颤振中,如何将validator 传递给textformfield

【问题讨论】:

    标签: android ios dart flutter


    【解决方案1】:

    您可以像传递给其他人一样简单地将验证器作为参数传递。您只需要传入一个将字符串作为参数并返回字符串的函数。

    //username validator possible structure
       Function(String) usernameValidator = (String username){
            if(username.isEmpty){
              return 'Username empty';
            }else if(username.length < 3){
              return 'Username short';
            }
    
            return null;
      };
    
      //password validator possible structure
      passwordValidator(String password){
            if(password.isEmpty){
              return 'Password empty';
            }else if(password.length < 3){
              return 'PasswordShort';
            }
            return null;
      }  
    
    
    
     //new build function
    Widget _buildInputFields(
        String label,
        TextEditingController textController,
        TextInputType textInputType,
        IconData icon,
        Color iconColor,
        String Function(String) validator
      ) {
        return Container(
            margin: EdgeInsets.only(left: 20, bottom: 20),
            child: Container(
              padding: EdgeInsets.only(right: 20),
              child: Row(
                children: <Widget>[
                  Flexible(
                    child: TextFormField(
                      controller: textController,
                      validator: validator,
                      style: new TextStyle(color: Colors.white),
                      keyboardType: textInputType,
                      decoration: InputDecoration(
                          labelText: label,
                          fillColor: Colors.white,
                          labelStyle: TextStyle(
                              color: Colors.white, fontWeight: FontWeight.w600),
                          enabledBorder: OutlineInputBorder(
                            borderSide:
                                const BorderSide(color: Colors.white30, width: 2.0),
                            borderRadius: BorderRadius.circular(25.0),
                          ),
                          suffixIcon: IconButton(
                            icon: Icon(icon, color: iconColor),
                            onPressed: () {},
                          )),
                    ),
                  ),
                ],
              ),
            ));
      }
    
        //calling your function
       _buildInputFields(label, textController, textInputType, icon, iconColor, usernameValidator);
       _buildInputFields(label, textController, textInputType, icon, iconColor, passwordValidator);
    

    【讨论】:

    • 所以值会自动传递给验证器? bcs 我没有看到类似validator: validatorMethod(value)
    • 是的。它会自动通过。验证器知道何时调用该函数。您只需要将它作为参数传递。
    • 它总是显示“用户名为空”,似乎没有收到更新的值
    • @Soumen。它不应该。我可能需要查看您的代码才能知道它有什么问题。
    • 我有两个文本字段(密码和确认密码)。所以用确认密码来验证密码。我需要传递参数(密码值)来检查该值是否等于确认密码。我会怎么做?它会自动传递参数??
    【解决方案2】:

    nonybrighto 答案完全正确,但添加空检查后更新代码是

    // Function to create form field
    Widget createFormField(String label, TextEditingController controller,
      String? Function(String?)? validator) {
    return TextFormField(
      decoration: InputDecoration(labelText: label),
      controller: controller,
      autovalidate: true,
      validator: validator,
    );
    }
    
    // Validator
    String? Function(String?)? idValidator = (String? value) {
    if (value!.isEmpty) {
      return 'Id Must be entered';
    } else {
      return int.tryParse(value) == null ? 'Id Must be number' : null;
    }
     };
    
    // Finally
    createFormField('Id', idController, idValidator),
    

    【讨论】:

      【解决方案3】:

      由于您已经在使用验证器,我想您只需将其作为参数传递到 _buildInputFields 中,对吧?

      应该是这样的:

      Widget _buildInputFields(
      ...
          Color iconColor,
          Function validator,
        ) {
      ...
                      child: TextFormField(
                        controller: textController,
                        validator: validator,
                        style: new TextStyle(color: Colors.white),
      ...
        }
      

      你可以使用它,你会很好的。

      但是,您可以更具体地使用验证器 Function 类型,如下所示:

      Widget _buildInputFields(
      ...
          Color iconColor,
          FormFieldValidator<String> validator,
      ...
      

      因此,您可以将验证器定义为 State 类的方法并重用它们,或者直接在 _buildInputFields 调用中指定它们。

      在下面的示例中,您有一个字段 Name,它使用 _notEmptyValidator,这是在同一类中定义的一种方法。由于 LastName 遵循相同的逻辑,因此它重用了此方法。

      ...
       String _notEmptyValidator(String value) {
         if (value.isEmpty) {
           return 'Please enter some text';
         }
       }
      ...
       Column(
        children: <Widget>[ 
          _buildInputFields("Name", _notEmptyValidator),
          _buildInputFields("Last Name", _notEmptyValidator),
      text" : null),
        ]
      ...
      

      在下面的示例中,我保留了以前的字段,但我正在添加一个新字段。这个新字段有一个非常具体的验证逻辑,我将在_buildInputFields调用中定义验证方法,因此不会在其他字段中重复使用。

      ...
       Column(
        children: <Widget>[ 
          _buildInputFields("Name", _notEmptyValidator),
          _buildInputFields("Last Name", _notEmptyValidator),
      text" : null),
          _buildInputFields("Valid Number", (value) {
            if (double.tryParse(value) == null) {
              return "Please input a valid number";
            }
          },
        ]
      ...
      

      【讨论】:

      • 谢谢你的回复,但我没听懂。我有兴趣分别定义 validator 方法。那么你如何将value 传递给验证器?请注意,如果我使用_buildInputFields 10 次,我可能会将 10 个不同的验证器传递给每个验证器。
      • 这正是最后一个 sn-p 的内容,你看,我已经调用了 _buildInputFields 2 次,创建了两个不同的字段,“名称”和“另一个名称”。他们使用不同的验证器,尽管在这个例子中两个验证器都做同样的事情。我会改进最后的sn-p。
      【解决方案4】:

      如果您需要向您的方法发送的不仅仅是值,您还可以在验证器中创建一个内部函数。 为了在验证器中实现内部化,我需要它。

      TextFormField(
        // The validator receives the text that the user has entered.
        validator: (value) {
          return myMethod(value, context, ...);
        },
        //... other attributes
      )
      
      

      【讨论】:

        【解决方案5】:

        对于 Flutter 2

        Custom Widget Function

        CupertinoTextFormFieldRow customTextField(
            String pretext, String supportText, Function(String) validatorFun) {
          return CupertinoTextFormFieldRow(
            prefix: Text(pretext),
            placeholder: supportText,
            validator: (val) => validatorFun(val!),
          );
        }
        

        Define validator functions

        acceptNonNull(String value) {
          if (value.trim().isEmpty) {
            return 'Please enter a value';
          }
          return null;
        }
        
        checkPassword(String value) {
          if (value.isEmpty) {
            return 'Password empty';
          } else if (value.length < 8) {
            return 'Password too weak';
          } //accept only if string contains both alphabests and numerics
            else if (!value.contains(RegExp(r'^[a-zA-Z0-9]+$'))) {
            return 'Password should contain aplpha numeric characters';
          }
          return null;
        }
        

        Build your Widgets

        customTextField("First Name", "Enter Your First Name Here",acceptNonNull),
        customTextField("Last Name", "Enter Your Last Name Here", acceptNonNull),
        customTextField("Password", "Choose a Password", checkPassword)
        

        【讨论】:

          【解决方案6】:

          只是一个简单的例子,使用nullsafety,flutter 2,getx

          登录屏幕

            validator: (value) {
               return AuthController.instance.emailValidator(AuthController.instance.emailController.text);
           },
          

          Auth_Controller

          emailValidator(String email){
              if ((!email.contains('@')) ||
                (email.trim().length < 8))
              {
                return 'Invalid email';
              }
              //validado com sucesso
              return null;
            }
          

          【讨论】:

            猜你喜欢
            • 2021-11-11
            • 1970-01-01
            • 1970-01-01
            • 2019-12-04
            • 2019-04-11
            • 1970-01-01
            • 1970-01-01
            • 2020-07-12
            • 2023-01-12
            相关资源
            最近更新 更多