在Stateless小部件中使用TextFormField非常困难

问题描述 投票:3回答:2

我试图在无状态小部件中使用TextFormField以及ScopedModel来处理其中的文本并面临如下的各种问题。

  1. 我尝试使用控制器进行字段,但每次我输入一些文本并在键盘上按完,文本就会被清除。不知道为什么。
  2. 如果我删除控制器,文本将保留在字段中,但会创建有关如何从字段获取文本的新问题。我通过使用回调onFieldSubmitted来解决它。
  3. 但事实证明,当我们点击键盘上的完成按钮时,onFieldSubmitted才被调用。如果我在字段中输入文本而不是单击确定,单击另一个字段,将不会调用回调,我将无法跟踪用户在字段中输入的内容。

对此有何解决方案?

附加问题的示例代码。

  class LoginPageStateless extends StatelessWidget {

  final loginUsernameController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomPadding: true,
      body: ScopedModelDescendant<AccountModel>(
        builder: (context, child, model) {
          return Form(
            //key: _formKey,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                TextFormField(
                  style: TextStyle(fontSize: 15.0),
                  decoration: InputDecoration(
                    labelText: 'Email id',
                    hintText: '[email protected]',
                  ),
                  controller: loginUsernameController,
                  onFieldSubmitted: model.updateLoginUsernameText,
                ),
                TextFormField(
                  style: TextStyle(fontSize: 15.0),
                  decoration: InputDecoration(
                    labelText: 'Password',
                  ),
                  controller: loginUsernameController,
                  onFieldSubmitted: model.updateLoginUsernameText,
                  obscureText: true,
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}
android ios flutter flutter-layout
2个回答
8
投票

您不能也不应该使用Stateless小部件来存储长期变量。

问题是,这正是你想要的。 TextEditingController是一个应该在渲染之间保持的类实例。但是通过将其存储到StatelessWidget中,您基本上可以在每次更新后重新创建它。

您应该将您的小部件转换为Stateful。并将该控制器移动到State部分


2
投票

到目前为止我还没有使用TextFormField,我总是使用TextField()来实现它的简单性和灵活性。我在使用Redux和无状态小部件时遇到了类似的问题,因为我在顶级商店中只有一个事实来源。所以,我必须在ViewModel中创建一些回调,然后将该回调分配给文本字段回调'onChanged',它接受一个字符串参数。

CustomTextWidgetWrapper(
    onChangedCallback: viewModel.onChanged
),

在我做的小部件包含的TextField中(没有提供更多细节)

new TextField(
    controller: myController, // no use practically now
    onChanged: onChangedCallback,

在视图模型中,我将字符串和调度发送到中央存储,以便在其他小部件中重用,例如一个获取数据并发送到服务器的按钮

static ViewModel fromStore(Store<AppState> store) {
    return new ViewModel(
        onChanged: (String textFieldText) {
            // I call dispatch or an API here if I want
            store.dispatch(new CallAPI(params: textFieldText);
© www.soinside.com 2019 - 2024. All rights reserved.