DropdownButton 选择调用 Flutter 中其他字段的 onValidate 函数

Posted

技术标签:

【中文标题】DropdownButton 选择调用 Flutter 中其他字段的 onValidate 函数【英文标题】:DropdownButton selection calls the onValidate functions of other fields in Flutter 【发布时间】:2020-11-26 20:30:56 【问题描述】:

不知道我错过了什么。选择下拉列表的值时,表单onVaidate() 被触发,因此我的其他字段显示错误。我怎样才能阻止它?这是代码

小部件构建(BuildContext 上下文) //返回脚手架( // appBar: AppBar(title: Text("Registration")), // body: Center(child: Text(widget.user.displayName)), // );

FirebaseUser user = widget.user;

  return Scaffold(
  key: _scaffoldKey,
  appBar: AppBar(
    title: Text("Registration"),
  ),
  body: SafeArea(
      top: false,
      bottom: false,
      child: Form(
          key: _formKey,
          autovalidate: true,
          child: ListView(
            padding: const EdgeInsets.symmetric(horizontal: 16.0),
            children: <Widget>[
              TextFormField(
                validator: (value) => value.isEmpty ? 'Name is Required' : null,
                decoration: const InputDecoration(
                  icon: const Icon(Icons.person),
                  hintText: 'Enter your first and last name',
                  labelText: 'Name',
                ),
              ),
              TextFormField(
                decoration: const InputDecoration(
                  icon: const Icon(Icons.phone),
                  hintText: 'Enter a phone number',
                  labelText: 'Phone',
                ),
                initialValue: user.phoneNumber,
                enabled: user.phoneNumber == null,
                keyboardType: TextInputType.phone,
                validator: (value) => value.isEmpty ? 'Phone number is Required' : null

                // inputFormatters: [
                //   WhitelistingTextInputFormatter.digitsOnly, 
                // ],
              ),
              TextFormField(
                decoration: const InputDecoration(
                  icon: const Icon(Icons.email),
                  hintText: 'Enter a email address',
                  labelText: 'Email',
                ),
                initialValue: user.email,
                enabled: user.email == null,
                validator: (value) => value.isEmpty ? 'Email is Required' : null,
                keyboardType: TextInputType.emailAddress,
              ),
              TextFormField(
                decoration: const InputDecoration(
                  icon: const Icon(Icons.remove_red_eye),
                  hintText: 'Enter the Password',
                  labelText: 'Password',
                ),
                keyboardType: TextInputType.text,
                obscureText: true,
                validator: (value) => value.isEmpty ? 'Password is Required' : null
              ),  
              FormField(
                builder: (FormFieldState state) 
                  return InputDecorator(
                    decoration: InputDecoration(
                      icon: const Icon(Icons.card_membership),
                      labelText: 'ID Type',
                    ),
                    isEmpty: _profile.govId == null,
                    child: DropdownButtonHideUnderline(
                      child: DropdownButton(
                        value: _profile.govId,
                        isDense: true,
                        onChanged: (String newValue) 
                          setState(() 
                            _profile.govId = newValue;
                            state.didChange(newValue);
                          );
                        ,
                        items: _govtIds.map((String value) 
                          return DropdownMenuItem(
                            value: value,
                            child: Text(value),
                          );
                        ).toList(),
                      ),
                    ),
                  );
                ,
              ),
              TextFormField(
                decoration: const InputDecoration(
                  icon: const Icon(Icons.confirmation_number),
                  hintText: 'Enter your Governmenr ID number',
                  labelText: 'ID Number',
                ),
                keyboardType: TextInputType.datetime,
                validator: (value) => value.isEmpty ? 'ID Number is Required' : null
              ),
              FormField(
                builder: (FormFieldState state) 
                  return InputDecorator(
                    decoration: InputDecoration(
                      icon: const Icon(Icons.business),
                      labelText: 'Block Info',
                    ),
                    isEmpty: _profile.block == null,
                    child: 
                    
                    // Column(children: [RadioListTile(title: Text("A")),RadioListTile(title: Text("B"))]),
                    
                    
                    // Radio(
                    //   value: 0,
                    //   groupValue: _blocks,
                    //   onChanged: (value)),
                    
                    DropdownButtonHideUnderline(
                      child: 
                      DropdownButton(
                        value: _profile.block,
                        isDense: true,
                        onChanged: (String newValue) 
                          setState(() 
                            _profile.block = newValue;
                            state.didChange(newValue);
                          );
                        ,
                        items: _blocks.map((String value) 
                          return DropdownMenuItem(
                            value: value,
                            child: Text(value),
                          );
                        ).toList(),
                      ),
                    ),
                  );
                ,
              ),
               TextFormField(
                decoration: const InputDecoration(
                  icon: const Icon(Icons.home),
                  hintText: 'Enter your Flat number',
                  labelText: 'Flat number',
                ),
                 inputFormatters: [LengthLimitingTextInputFormatter(3)],
                validator: (value) 
                  if (value.isEmpty) 
                    return 'Flat number is Required';
                   else if (_profile.isValidHouseNumber() == false) 
                    return 'Invalid flat number';
                   else 
                    return null;
                  
                ,
                keyboardType: TextInputType.number,
                onChanged:(value) 
                  _profile.houseNo = value;
                ,
              ),
                Padding(
                padding: EdgeInsets.fromLTRB(38.0, 30.0, 0.0, 0.0),
                child: SizedBox(
                height: 50.0,
                child: FlatButton(
                  // elevation: 5.0,
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10.0)),
                  color: Colors.green,
                  child: Text('Submit',
                      style: TextStyle(fontSize: 20.0, color: Colors.white)),
                  onPressed: _validateAndSubmit,
                ),
              ))
    ],
  ))),
);

【问题讨论】:

【参考方案1】:

在验证功能中调用一个方法以返回 null 所有其他字段。这将清除验证。这是一个修复,但不能解决问题。

上面的代码好像没什么问题,能不能把其他字段的代码也加一下?

编辑:

所有其他字段验证的原因是父窗体小部件的autovalidate: true 属性。删除它并使用带有different keys 的表单将每个 TextFormField 包装起来。

例如,您的TextFormField 应如下所示:

Form(
  key: _formKey[0],
  child: TextFormField(
    validator: (value) => value.isEmpty ? 'Name is Required' : null,
    decoration: const InputDecoration(
      icon: const Icon(Icons.person),
      hintText: 'Enter your first and last name',
      labelText: 'Name',
    ),
  ),
),

用Form包裹起来,_formKey声明为

List&lt;GlobalObjectKey&lt;FormState&gt;&gt; _formKey = new List(number_of_keys);

像这样调用相应的 setState:

_formKey[position].currentState.setState(());

并且不要忘记删除父窗体小部件。

【讨论】:

添加了完整的构建方法 不要将所有的 TextFormFields 包装在一个表单中,这不是好的代码。使用表单的不同键单独包装。这样可以确保可以单独验证字段而不影响其他字段。

以上是关于DropdownButton 选择调用 Flutter 中其他字段的 onValidate 函数的主要内容,如果未能解决你的问题,请参考以下文章

选择项目时,颤振不更新放置在对话框中的 DropdownButton

Flutter - 如何在小部件测试中选择 DropdownButton 项

在 DropdownButton 中选择 Item 会导致 Flutter 抛出错误

从 DropdownItems 中选择值后,DropdownButton 值未更新。如何使用 selectedValue 更新默认值?

Flutter:按钮下方的 DropDownButton 项

应该只有一项具有 [DropdownButton] 的值:“合作伙伴”的实例