如何正确预填充颤振表单字段?
Posted
技术标签:
【中文标题】如何正确预填充颤振表单字段?【英文标题】:How to properly pre-fill flutter form field? 【发布时间】:2017-09-29 04:03:45 【问题描述】:我正在尝试创建一个“编辑个人资料”页面,在该页面中加载所有用户数据并让用户对其进行修改。但是,同时使用TextEditingController
上的value
和text
属性会导致无法修改TextFormField
中的数据。我可以添加到它的开头,但我不能从中删除任何字符。
为了进一步详细说明这种行为,在下面的屏幕截图中,我可以在字段中输入更多内容(就像我输入“Asdf”一样),但是从光标所在的位置开始,我无法将光标向右移动或删除"F" 或任何原本放置在那里的字符。
在TextFormField
的OnSaved
函数中,value
参数是提交时表单的全文,在本例中为“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;
,
),
),
],
)));
这里是flutter doctor
:
% flutter doctor
[✓] Flutter (on Mac OS X 10.12.6 16G29, locale en-US, channel alpha)
• Flutter at /Users/frederickcook/flutter
• Framework revision 701d534ba9 (2 weeks ago), 2017-09-12 14:01:51 -0700
• Engine revision 31d03de019
• Tools Dart version 1.25.0-dev.11.0
[✓] android toolchain - develop for Android devices (Android SDK 26.0.0)
• Android SDK at /Users/frederickcook/Library/Android/sdk
• Platform android-26, build-tools 26.0.0
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_112-release-b06)
[✓] ios toolchain - develop for iOS devices (Xcode 9.0)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 9.0, Build version 9A235
• ios-deploy 1.9.2
• CocoaPods version 1.2.1
[✓] Android Studio (version 2.3)
• Android Studio at /Applications/Android Studio.app/Contents
• Java version OpenJDK Runtime Environment (build 1.8.0_112-release-b06)
[✓] IntelliJ IDEA Community Edition (version 2017.2.5)
• Flutter plugin version 17.0
• Dart plugin version 172.4155.35
[✓] Connected devices
• iPhone 7 • 2AE532E3-5B4B-4D8D-8CFB-F54C3BF6F8EE • ios • iOS 11.0 (simulator)
【问题讨论】:
【参考方案1】:使用initialValue:
属性可以很好地与TextFormField
配合使用。
【讨论】:
有这个属性吗?我在TextField
中没有看到initialValue
。
@Ixx 我认为你是对的我编辑了我的回复。我猜只有 TextFormField
有一个 initialValue
属性很奇怪。
当您使用无状态小部件并使用未更改的属性来获取文本值时,这实际上会有所帮助。另外,你忘了提到在这种情况下不应该使用控制器
这个对我个人很有帮助。【参考方案2】:
想通了:从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;
,
),
),
],
)));
【讨论】:
太棒了!非常感谢! 我觉得这个解决方案非常正确,虽然预填充文本可以在 super.init 之后进行管理【参考方案3】:TextFormField
具有 initialValue
属性。
要使用 TextField
完成此操作,您可以使用 控制器 来设置初始值:
final _controllerFirstName = TextEditingController();
_controllerFirstName.text = 'First Name here';
TextField(
controller: _controllerFirstName,
onChanged: (nameVal) => setState(()
_displayName = nameVal;
),
),
// to clear the controller
_controllerFirstName.clear();
【讨论】:
以上是关于如何正确预填充颤振表单字段?的主要内容,如果未能解决你的问题,请参考以下文章