Flutter自定义FormField:不调用validate和save方法 [英] Flutter custom FormField : validate and save methods are not called

查看:511
本文介绍了Flutter自定义FormField:不调用validate和save方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Flutter还是很陌生,并且我在创建自定义表单字段方面有些挣扎.问题是我的自定义FormField中的验证器和onSaved方法都没有被调用.我真的不知道为什么当我触发formKey.currentState.validate()formKey.currentState.save()时它们会被忽略.

I am quite new to Flutter, and I am struggling a bit to create a custom Form Field. The issue is that neither the validator nor the onSaved method from my custom FormField are called. I really am clueless on why they get ignored when I trigger a formKey.currentState.validate() or formKey.currentState.save().

这是一个非常简单的小部件,带有输入文本和按钮. 该按钮将获取用户的当前位置,并使用当前地址更新文本字段. 当用户在文本字段中输入地址时,它将失去焦点时获取该地址的位置(我也与Google Maps集成,但是我简化了此操作以隔离问题).

This is a pretty simple widget for now, with an input text and a button. The button will fetch the current location of the user, and update the text field with the current address. When the user inputs an address in the text field, it will fetch the location for that address on focus lost (I have also integration with Google Maps, but I simplified it to isolate the issue).

这是我的表单字段的构造函数:

Here is the constructor of my form field :

class LocationFormField extends FormField<LocationData> {

    LocationFormField(
          {FormFieldSetter<LocationData> onSaved,
          FormFieldValidator<LocationData> validator,
          LocationData initialValue,
          bool autovalidate = false})
          : super(
                onSaved: onSaved,
                validator: validator,
                initialValue: initialValue,
                autovalidate: autovalidate,
                builder: (FormFieldState<LocationData> state) {
                  return state.build(state.context);
                });

      @override
      FormFieldState<LocationData> createState() {
        return _LocationFormFieldState();
      }
}

由于我需要在自定义FormField中处理状态,因此我在FormFieldState对象中构建状态.当按下按钮时,位置状态会更新:

As I need to handle state in my custom FormField, I build it in the FormFieldState object. The location state is updated when the button is pressed :

class _LocationFormFieldState extends FormFieldState<LocationData> {

 @override
 Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        TextField(
          focusNode: _addressInputFocusNode,
          controller: _addressInputController,
          decoration: InputDecoration(labelText: 'Address'),
        ),
        SizedBox(height: 10.0),
        FlatButton(
          color: Colors.deepPurpleAccent,
          textColor: Colors.white,
          child: Text('Locate me !'),
          onPressed: _updateLocation,
        ),
      ],
    );
  }

  void _updateLocation() async {
    print('current value: ${this.value}');
      final double latitude = 45.632;
      final double longitude = 17.457;
      final String formattedAddress = await _getAddress(latitude, longitude);
      print(formattedAddress);

      if (formattedAddress != null) {
        final LocationData locationData = LocationData(
            address: formattedAddress,
            latitude: latitude,
            longitude: longitude);

          _addressInputController.text = locationData.address;

        // save data in form
        this.didChange(locationData);
        print('New location: ' + locationData.toString());
        print('current value: ${this.value}');
    }
  }

这就是我在应用程序中实例化它的方式.这里没什么特别的;我将其放在带有表单键的表单中.还有另一个TextFormField可以验证它是否正常工作:

This is how I instantiate it in my app. Nothing special here; I put it in a Form with a form key. There is another TextFormField to verify that this one is working fine:

main.dart

Widget _buildLocationField() {
        return LocationFormField(
          initialValue: null,
          validator: (LocationData value) {
            print('validator location');
            if (value.address == null || value.address.isEmpty) {
              return 'No valid location found';
            }
          },
          onSaved: (LocationData value) {
            print('location saved: $value');
            _formData['location'] = value;
          },
        ); // LocationFormField
      }

@override
  Widget build(BuildContext context) {
    return Scaffold(
          appBar: AppBar(
            // Here we take the value from the MyHomePage object that was created by
            // the App.build method, and use it to set our appbar title.
            title: Text(widget.title),
          ),
          body: Center(
            // Center is a layout widget. It takes a single child and positions it
            // in the middle of the parent.
            child: Container(
              margin: EdgeInsets.all(10.0),
              child: Form(
                key: _formKey,
                child: SingleChildScrollView(
                  padding: EdgeInsets.symmetric(horizontal: targetPadding / 2),
                  child: Column(
                    children: <Widget>[
                      _buildTitleTextField(),
                      SizedBox(
                        height: 10.0,
                      ),
                      _buildLocationField(),
                      SizedBox(
                        height: 10.0,
                      ),
                      _buildSubmitButton(),
                    ],
                  ),
                ),
              ),
            ),
          ),
        );
      }

由表单提交按钮触发的submit方法将仅尝试验证然后保存表单.

The submit method triggered by the form submit button will just try to validate then save the form.

只需打印以以下格式保存的数据:

Just printing the data saved in the form:

void _submitForm() {
    print('formdata : $_formData');

    if (!_formKey.currentState.validate()) {
      return;
    }
    _formKey.currentState.save();

    print('formdata : $_formData');
}

但是_formData['location']始终返回null,并且永远不会调用验证程序(日志中没有打印验证程序位置"或保存的位置").

But _formData['location'] always returns null, and the validator is never called (no 'validator location' or 'location saved' printed in logs).

我创建了一个示例存储库来重现此问题.您可以尝试运行该项目,首先单击查找我!".按钮,然后点击 https://github.com/manumura/flutter-location-表单字段

I created a sample repo to reproduce this issue. You can try running the project, click first on the Locate me ! button, then the Save button at https://github.com/manumura/flutter-location-form-field

推荐答案

出现相同的问题.对我来说,当我更换时它起作用了

Had the same problem. For me it worked when I replaced

return state.build(state.context);

使用build方法中的实际代码,并从状态中删除了build方法覆盖.

With actual code from the build method and removed the build method override from the state.

这篇关于Flutter自定义FormField:不调用validate和save方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆