Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 颤振:当字段在ListView中不可见时,未调用TextFormField验证程序_Flutter_Dart - Fatal编程技术网

Flutter 颤振:当字段在ListView中不可见时,未调用TextFormField验证程序

Flutter 颤振:当字段在ListView中不可见时,未调用TextFormField验证程序,flutter,dart,Flutter,Dart,我也遇到过同样的问题,我按照提供的建议解决了这个问题(我在onChanged中调用setState())。。。问题是,在我的例子中,如果字段在视图中不可见(如果滚动视图直到不再显示),则不会调用validator函数,因此我可以在无效状态下提交表单 如何触发当前未显示在列表视图中的字段的验证 更新: 以下是该问题的简单演示(我正在一个独立的简单应用程序中使用它进行调试): 导入“包装:颤振/材料.省道”; void main()=>runApp(MyApp()); 类MyForm扩展了State

我也遇到过同样的问题,我按照提供的建议解决了这个问题(我在
onChanged
中调用
setState()
)。。。问题是,在我的例子中,如果字段在视图中不可见(如果滚动视图直到不再显示),则不会调用
validator
函数,因此我可以在无效状态下提交表单

如何触发当前未显示在
列表视图中的字段的验证

更新:

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

导入“包装:颤振/材料.省道”;
void main()=>runApp(MyApp());
类MyForm扩展了StatefulWidget{
@凌驾
状态createState(){
返回_MyFormState();
}
}
类_MyFormState扩展了状态{
静态最终全局键_formKey=GlobalKey();
最终地图模型=地图();
@凌驾
void initState(){
打印('initState()');
对于(int i=0;i<20;i++){
模型[i]=null;
}
super.initState();
}
字符串验证(字符串值){
返回值.isEmpty?不能为空!:null;
}
void submitForm(){
final FormState FormState=\u formKey.currentState;
if(formState.validate()){
打印(“表格有效”);
formState.save();
}否则{
打印('表格无效');
}
}
@凌驾
小部件构建(构建上下文){
列表字段=[];
对于(int i=0;i<20;i++){
Widget Widget=TextFormField(
初始值:模型[i],
装饰:输入装饰(
labelText:“字段$i”,
),
验证程序:验证,
onFieldSubmitted:(字符串值){
打印('field$i onFieldSubmitted()');
设置状态(){
模型[i]=数值;
});
},
onChanged:(字符串值){
打印('field$i onChanged()');
设置状态(){
模型[i]=数值;
});
},
onSaved:(字符串值){
打印('field$i onSaved()');
设置状态(){
模型[i]=数值;
});
},
);
添加(小部件);
}
字段。添加(RaisedButton(
子项:文本('save'),
onPressed:submitForm,
));
报税表(
键:_formKey,
子:ListView(
孩子们:田野,
),
);
}
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“颤振演示”,
主题:主题数据(
主样本:颜色。蓝色,
),
家:脚手架(
appBar:appBar(
标题:文本(“形式测试”),
),
正文:MyForm(),
),
);
}
}

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

解决方案很简单,只是不要使用
列表视图
,而是依赖
SingleChildScrollView
(并将表单本身作为子表单传递)

导入“包装:颤振/材料.省道”;
void main()=>runApp(MyApp());
类MyForm扩展了StatefulWidget{
@凌驾
状态createState(){
返回_MyFormState();
}
}
类_MyFormState扩展了状态{
静态最终全局键_formKey=GlobalKey();
最终地图模型=地图();
@凌驾
void initState(){
打印('initState()');
对于(int i=0;i<20;i++){
模型[i]=null;
}
super.initState();
}
字符串验证(字符串值){
返回值.isEmpty?不能为空!:null;
}
void submitForm(){
final FormState FormState=\u formKey.currentState;
if(formState.validate()){
打印(“表格有效”);
formState.save();
}否则{
打印('表格无效');
}
}
@凌驾
小部件构建(构建上下文){
列表字段=[];
对于(int i=0;i<20;i++){
Widget Widget=TextFormField(
初始值:模型[i],
装饰:输入装饰(
labelText:“字段$i”,
),
验证程序:验证,
onFieldSubmitted:(字符串值){
打印('field$i onFieldSubmitted()');
设置状态(){
模型[i]=数值;
});
},
);
添加(小部件);
}
字段。添加(RaisedButton(
子项:文本('save'),
onPressed:submitForm,
));
返回SingleChildScrollView(
孩子:表格(
键:_formKey,
子:列(
孩子们:田野,
),
),
);
}
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“颤振演示”,
主题:主题数据(
主样本:颜色。蓝色,
),
家:脚手架(
appBar:appBar(
标题:文本(“形式测试”),
),
正文:MyForm(),
),
);
}
}

您所说的“提供者”是什么意思?这个->?如果您不想使用提供程序。。您可以在widget类中的单独方法中编写验证逻辑。问题不在验证逻辑中,如果字段在视图中可见,则所有字段验证程序都可以正常工作。。。关键是,如果字段不可见,
FormState
validate()
在调用validate()后,不会调用隐藏字段的验证器(换句话说,这就像是针对表单的一部分而不是完整字段进行验证)。如果字段滚动到视图中,是否会显示错误?是,正如我所写的,只要字段当前显示在视图中,验证工作正常
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<FormState>();
  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;
          });
        },
        onChanged: (String value) {
          print('field $i onChanged()');
          setState(() {
            model[i] = value;
          });
        },
        onSaved: (String value) {
          print('field $i onSaved()');
          setState(() {
            model[i] = value;
          });
        },
      );
      fields.add(widget);
    }

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

    return Form(
      key: _formKey,
      child: ListView(
        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(),
      ),
    );
  }
}
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(),
      ),
    );
  }
}