Forms 如何正确预填颤振表单字段?

Forms 如何正确预填颤振表单字段?,forms,flutter,Forms,Flutter,我试图创建一个“编辑配置文件”页面,在其中加载所有用户数据并允许用户修改。但是,在文本编辑控制器上同时使用值和文本属性会导致无法修改文本表单字段中的数据。我可以添加到它的开头,但不能从中删除任何字符 为了进一步阐述这一行为,在下面的屏幕截图中,我可以在字段中键入更多内容(就像我在“Asdf”中所做的那样),但从光标所在的位置,我无法将光标向右移动或删除“F”或最初放置在那里的任何字符 在TextFormField的OnSaved功能中,值参数是提交时表单的全文,在本例中为“AsdfFreder

我试图创建一个“编辑配置文件”页面,在其中加载所有用户数据并允许用户修改。但是,在
文本编辑控制器
上同时使用
文本
属性会导致无法修改
文本表单字段
中的数据。我可以添加到它的开头,但不能从中删除任何字符

为了进一步阐述这一行为,在下面的屏幕截图中,我可以在字段中键入更多内容(就像我在“Asdf”中所做的那样),但从光标所在的位置,我无法将光标向右移动或删除“F”或最初放置在那里的任何字符

TextFormField
OnSaved
功能中,
参数是提交时表单的全文,在本例中为“AsdfFrederick”

这是我的密码:

import 'dart:async';
import 'package:flutter/material.dart';
import '../models/user.dart';

class EditProfileView extends StatefulWidget {
  @override
  _EditProfileViewState createState() => new _EditProfileViewState();
}

class _EditProfileViewState extends State<EditProfileView> {
  final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();

  void _handleSubmitted() {
    final FormState form = _formKey.currentState;
    if (!form.validate()) {
    } else {
      form.save();
      User.instance.save().then((result) {
        print("Saving done: ${result}.");
        Navigator.pop(context);
      });
    }
  }


  @override
  Widget build(BuildContext context) {
    final ThemeData themeData = Theme.of(context);
    final DateTime today = new DateTime.now();

    // controllers for form text controllers
    final TextEditingController _firstNameController =
        new TextEditingController();
    //_firstNameController.value = new TextEditingValue(text: User.instance.first_name);
    _firstNameController.text = User.instance.first_name;
    final TextEditingController _lastNameController =
        new TextEditingController();
    _lastNameController.text = User.instance.last_name;

    return new Scaffold(
        appBar: new AppBar(title: const Text('Edit Profile'), actions: <Widget>[
          new Container(
              padding: const EdgeInsets.fromLTRB(0.0, 10.0, 5.0, 10.0),
              child: new MaterialButton(
                color: themeData.primaryColor,
                textColor: themeData.secondaryHeaderColor,
                child: new Text('Save'),
                onPressed: () {
                  _handleSubmitted();
                  Navigator.pop(context);
                },
              ))
        ]),
        body: new Form(
            key: _formKey,
            autovalidate: _autovalidate,
            onWillPop: _warnUserAboutInvalidData,
            child: new ListView(
              padding: const EdgeInsets.symmetric(horizontal: 16.0),
              children: <Widget>[
                new Container(
                  child: new TextFormField(
                    decoration: const InputDecoration(labelText: "First Name", hintText: "What do people call you?"),
                    autocorrect: false,
                    controller: _firstNameController,
                    onSaved: (String value) {
                      User.instance.first_name = value;
                    },
                  ),
                ),
                new Container(
                  child: new TextFormField(
                    decoration: const InputDecoration(labelText: "Last Name"),
                autocorrect: false,
                controller: _lastNameController,
                onSaved: (String value) {
                  User.instance.last_name = value;
                },
              ),
            ),
          ],
        )));
  }
}

解决方法:从
TextFormField
切换到
TextField
,创建局部变量来存储对字段的更改,并使用
initState
设置初始表单值,而不是在
build
中进行设置

import 'dart:async';
import 'package:flutter/material.dart';
import '../models/user.dart';

class EditProfileView extends StatefulWidget {
  @override
  _EditProfileViewState createState() => new _EditProfileViewState();
}

class _EditProfileViewState extends State<EditProfileView> {
  final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();

  void _handleSubmitted() {
    final FormState form = _formKey.currentState;
    if (!form.validate()) {
      _autovalidate = true; // Start validating on every change.
      showInSnackBar('Please fix the errors in red before submitting.');
    } else {
      showInSnackBar('snackchat');
      User.instance.first_name = firstName;
      User.instance.last_name = lastName;

      User.instance.save().then((result) {
        print("Saving done: ${result}.");
      });
    }
  }

  // controllers for form text controllers
  final TextEditingController _firstNameController = new TextEditingController();
  String firstName = User.instance.first_name;
  final TextEditingController _lastNameController = new TextEditingController();
  String lastName = User.instance.last_name;

  @override
  void initState() {
    _firstNameController.text = firstName;
    _lastNameController.text = lastName;
    return super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final ThemeData themeData = Theme.of(context);
    final DateTime today = new DateTime.now();

    return new Scaffold(
        appBar: new AppBar(title: const Text('Edit Profile'), actions: <Widget>[
          new Container(
              padding: const EdgeInsets.fromLTRB(0.0, 10.0, 5.0, 10.0),
              child: new MaterialButton(
                color: themeData.primaryColor,
                textColor: themeData.secondaryHeaderColor,
                child: new Text('Save'),
                onPressed: () {
                  _handleSubmitted();
                  Navigator.pop(context);
                },
              ))
        ]),
        body: new Form(
            key: _formKey,
            autovalidate: _autovalidate,
            onWillPop: _warnUserAboutInvalidData,
            child: new ListView(
              padding: const EdgeInsets.symmetric(horizontal: 16.0),
              children: <Widget>[
                new Container(
                  child: new TextField(
                    decoration: const InputDecoration(labelText: "First Name", hintText: "What do people call you?"),
                    autocorrect: false,
                    controller: _firstNameController,
                    onChanged: (String value) {
                      firstName = value;
                    },
                  ),
                ),
                new Container(
                  child: new TextField(
                    decoration: const InputDecoration(labelText: "Last Name"),
                    autocorrect: false,
                    controller: _lastNameController,
                    onChanged: (String value) {
                      lastName = value;
                    },
                  ),
                ),
              ],
            )));
  }
}
导入'dart:async';
进口“包装:颤振/材料.省道”;
导入“../models/user.dart”;
类EditProfileView扩展了StatefulWidget{
@凌驾
_EditProfileViewState createState()=>new_EditProfileViewState();
}
类_EditProfileViewState扩展状态{
final GlobalKey _formKey=新GlobalKey();
void_handleSubmitted(){
final FormState form=\u formKey.currentState;
如果(!form.validate()){
_autovalidate=true;//开始对每个更改进行验证。
showinsnakbar('请在提交前用红色修复错误');
}否则{
showinsnakbar(“snackchat”);
User.instance.first_name=firstName;
User.instance.last_name=lastName;
User.instance.save().then((结果){
打印(“保存完成:${result}.”);
});
}
}
//表单文本控制器的控制器
最终文本编辑控制器_firstNameController=新文本编辑控制器();
String firstName=User.instance.first\u name;
final TextEditingController _lastNameController=新TextEditingController();
字符串lastName=User.instance.last\u name;
@凌驾
void initState(){
_firstNameController.text=firstName;
_lastNameController.text=lastName;
返回super.initState();
}
@凌驾
小部件构建(构建上下文){
最终主题数据主题数据=Theme.of(上下文);
final DateTime today=新的DateTime.now();
归还新脚手架(
appBar:new appBar(标题:常量文本(“编辑配置文件”),操作:[
新容器(
填充:LTRB(0.0,10.0,5.0,10.0)中的常数边集,
孩子:新材料按钮(
颜色:themeData.primaryColor,
textColor:themeData.secondaryHeaderColor,
子项:新文本(“保存”),
已按下:(){
_handleSubmitted();
Navigator.pop(上下文);
},
))
]),
正文:新表格(
键:_formKey,
自动验证:_自动验证,
onWillPop:_warnuersaboutinvaliddata,
子:新列表视图(
填充:常量边集。对称(水平:16.0),
儿童:[
新容器(
孩子:新文本字段(
装饰:const input装饰(labelText:“名字”,hintText:“人们叫你什么?”),
自动更正:错误,
控制器:_firstname控制器,
onChanged:(字符串值){
firstName=值;
},
),
),
新容器(
孩子:新文本字段(
装饰:常量输入装饰(标签文本:“姓氏”),
自动更正:错误,
控制器:\ u lastname控制器,
onChanged:(字符串值){
lastName=值;
},
),
),
],
)));
}
}

使用
初始值:
属性与
TextFormField

TextFormField
具有
初始值
属性

import 'dart:async';
import 'package:flutter/material.dart';
import '../models/user.dart';

class EditProfileView extends StatefulWidget {
  @override
  _EditProfileViewState createState() => new _EditProfileViewState();
}

class _EditProfileViewState extends State<EditProfileView> {
  final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();

  void _handleSubmitted() {
    final FormState form = _formKey.currentState;
    if (!form.validate()) {
      _autovalidate = true; // Start validating on every change.
      showInSnackBar('Please fix the errors in red before submitting.');
    } else {
      showInSnackBar('snackchat');
      User.instance.first_name = firstName;
      User.instance.last_name = lastName;

      User.instance.save().then((result) {
        print("Saving done: ${result}.");
      });
    }
  }

  // controllers for form text controllers
  final TextEditingController _firstNameController = new TextEditingController();
  String firstName = User.instance.first_name;
  final TextEditingController _lastNameController = new TextEditingController();
  String lastName = User.instance.last_name;

  @override
  void initState() {
    _firstNameController.text = firstName;
    _lastNameController.text = lastName;
    return super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final ThemeData themeData = Theme.of(context);
    final DateTime today = new DateTime.now();

    return new Scaffold(
        appBar: new AppBar(title: const Text('Edit Profile'), actions: <Widget>[
          new Container(
              padding: const EdgeInsets.fromLTRB(0.0, 10.0, 5.0, 10.0),
              child: new MaterialButton(
                color: themeData.primaryColor,
                textColor: themeData.secondaryHeaderColor,
                child: new Text('Save'),
                onPressed: () {
                  _handleSubmitted();
                  Navigator.pop(context);
                },
              ))
        ]),
        body: new Form(
            key: _formKey,
            autovalidate: _autovalidate,
            onWillPop: _warnUserAboutInvalidData,
            child: new ListView(
              padding: const EdgeInsets.symmetric(horizontal: 16.0),
              children: <Widget>[
                new Container(
                  child: new TextField(
                    decoration: const InputDecoration(labelText: "First Name", hintText: "What do people call you?"),
                    autocorrect: false,
                    controller: _firstNameController,
                    onChanged: (String value) {
                      firstName = value;
                    },
                  ),
                ),
                new Container(
                  child: new TextField(
                    decoration: const InputDecoration(labelText: "Last Name"),
                    autocorrect: false,
                    controller: _lastNameController,
                    onChanged: (String value) {
                      lastName = value;
                    },
                  ),
                ),
              ],
            )));
  }
}
要使用
TextField
完成此操作,您可以使用控制器设置初始值,如下所示:

final _controllerFirstName = TextEditingController();

_controllerFirstName.text = 'First Name here';

TextField(
  controller: _controllerFirstName,
  onChanged: (nameVal) => setState(() {
    _displayName = nameVal;
  }),
),

// to clear the controller
_controllerFirstName.clear();

这里有这个物业吗?我在
TextField
@Ixx中没有看到
initialValue
,我想你是对的,我编辑了我的回复。我猜只有
TextFormField
有一个
initialValue
属性非常奇怪。当您使用无状态小部件并使用unchanged属性获取文本值时,这实际上很有帮助。还有,你忘了提到控制器不应该在这种情况下使用这一个对我个人很有帮助。太棒了!!多谢各位!我发现这个解决方案非常正确,尽管在super.init之后可以管理预填充文本