Flutter:当ListView中的字段不可见时,不调用TextFormField验证器

时间:2019-11-05 09:55:26

标签: flutter dart

我遇到了同样的问题this question on SO,我通过遵循提供的建议解决了问题(我在setState()中称onChanged)...问题是我的情况是{如果该字段在视图中不可见(如果您滚动视图直到不再显示该视图),则不会调用{1}}函数,因此我可以以无效状态提交表单。

我应该如何触发validator中当前未显示的字段的验证?

更新:

以下是该问题的简单演示(我正在使用它在一个隔离的简单应用中进行调试):

ListView

2 个答案:

答案 0 :(得分:0)

我可以想到两种方法 1)您不能使用验证器。使用提供者的验证方法。如果提供者发回错误,请显示小吃店。 2)您可以使用验证器。您还必须在提供程序中使用验证方法。如果provider返回错误,请使用scrollcontroller滚动到所需的列表元素,并希望届时将激活表单字段验证器。

答案 1 :(得分:0)

解决方案很简单,只是不使用ListView而是依靠SingleChildScrollView(并将表单本身作为子元素传递)

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyForm extends StatefulWidget {
  @override
  State createState() {
    return _MyFormState();
  }
}

class _MyFormState extends State<MyForm> {
  static final GlobalKey<FormState> _formKey = GlobalKey();

  final Map<int, String> model = Map<int, String>();

  @override
  void initState() {
    print('initState()');
    for (int i = 0; i < 20; i++) {
      model[i] = null;
    }
    super.initState();
  }

  String validate(String value) {
    return value.isEmpty ? 'Cannot be blank!' : null;
  }

  void submitForm() {
    final FormState formState = _formKey.currentState;

    if (formState.validate()) {
      print('form is valid');
      formState.save();
    } else {
      print('form is invalid');
    }
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> fields = [];

    for (int i = 0; i < 20; i++) {
      Widget widget = TextFormField(
        initialValue: model[i],
        decoration: InputDecoration(
          labelText: 'field $i',
        ),
        validator: validate,
        onFieldSubmitted: (String value) {
          print('field $i onFieldSubmitted()');
          setState(() {
            model[i] = value;
          });
        },
      );
      fields.add(widget);
    }

    fields.add(RaisedButton(
      child: Text('save'),
      onPressed: submitForm,
    ));

    return SingleChildScrollView(
      child: Form(
        key: _formKey,
        child: Column(
          children: fields,
        ),
      ),
    );
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('form test'),
        ),
        body: MyForm(),
      ),
    );
  }
}