web-dev-qa-db-ja.com

ステートレスウィジェットでのTextFormFieldの使用は、フラッターでは非常に困難です。

ステートレスウィジェットでTextFormFieldをScopedModelと共に使用して、その中のテキストを処理しようとしています。次のようなさまざまな問題に直面しています。

  1. フィールドにコントローラを使用してみましたが、テキストを入力してキーボードの[done]を押すたびに、テキストがクリアされます。理由はわかりません。

  2. コントローラを削除すると、テキストがフィールドに残りますが、フィールドからテキストを取得する方法に関して新しい問題が発生します。コールバックonFieldSubmittedを使用して解決しました。

  3. しかし、結局のところ、onFieldSubmittedは、キーボードの完了ボタンをクリックしたときにのみ呼び出されます。フィールドにテキストを入力して[OK]をクリックする代わりに別のフィールドをクリックすると、コールバックが呼び出されず、ユーザーがフィールドに入力した内容を追跡する方法がありません。

これに対する解決策はありますか?

問題のサンプルコードを添付しています。

  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,
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}
8
Amit Bhandari

長期変数を格納するためにStatelessウィジェットを使用することはできません。

問題は、それがまさにあなたがしようとしていることです。 TextEditingControllerは、レンダリング間で保持する必要があるクラスインスタンスです。しかし、それをStatelessWidgetに保存することで、基本的には更新のたびに再作成します。

代わりに、ウィジェットをStatefulに変換する必要があります。そして、そのコントローラーをStateパーツに移動します

11
Rémi Rousselet

私はこれまで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);
2