【问题标题】:How to properly pre-fill flutter form field?如何正确预填充颤振表单字段?
【发布时间】:2017-09-29 04:03:45
【问题描述】:

我正在尝试创建一个“编辑个人资料”页面,在该页面中加载所有用户数据并让用户对其进行修改。但是,同时使用TextEditingController 上的valuetext 属性会导致无法修改TextFormField 中的数据。我可以添加到它的开头,但我不能从中删除任何字符。

为了进一步详细说明这种行为,在下面的屏幕截图中,我可以在字段中输入更多内容(就像我输入“Asdf”一样),但是从光标所在的位置开始,我无法将光标向右移动或删除"F" 或任何原本放置在那里的字符。

TextFormFieldOnSaved 函数中,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)

【问题讨论】:

    标签: forms flutter


    【解决方案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();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-06
      • 2021-08-05
      • 2020-11-24
      • 1970-01-01
      • 2017-04-28
      • 2021-01-06
      • 1970-01-01
      • 2012-12-20
      相关资源
      最近更新 更多