BLOG
Flutterでフォーム入力を管理する方法【TextEditingController・Form】
Flutterで入力フォームを作るときは、TextEditingController で入力値を扱い、Form と TextFormField で検証する形にすると保守しやすくなります。
この記事では、選手メモのような小さな入力画面を例に、controllerの作成、dispose、validator、送信処理までをまとめます。
サンプルコード
import 'package:flutter/material.dart';
class PlayerMemoForm extends StatefulWidget {
const PlayerMemoForm({super.key});
@override
State<PlayerMemoForm> createState() => _PlayerMemoFormState();
}
class _PlayerMemoFormState extends State<PlayerMemoForm> {
final _formKey = GlobalKey<FormState>();
final _nameController = TextEditingController();
final _memoController = TextEditingController();
@override
void dispose() {
_nameController.dispose();
_memoController.dispose();
super.dispose();
}
void _submit() {
final isValid = _formKey.currentState?.validate() ?? false;
if (!isValid) {
return;
}
final name = _nameController.text.trim();
final memo = _memoController.text.trim();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('$name のメモを保存しました')),
);
debugPrint('name: $name');
debugPrint('memo: $memo');
}
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextFormField(
controller: _nameController,
decoration: const InputDecoration(
labelText: '選手名',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.trim().isEmpty) {
return '選手名を入力してください';
}
return null;
},
),
const SizedBox(height: 16),
TextFormField(
controller: _memoController,
minLines: 3,
maxLines: 5,
decoration: const InputDecoration(
labelText: 'メモ',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.trim().length < 5) {
return '5文字以上で入力してください';
}
return null;
},
),
const SizedBox(height: 16),
FilledButton(
onPressed: _submit,
child: const Text('保存する'),
),
],
),
);
}
}
実装の流れ
GlobalKey<FormState>を作るTextEditingControllerを入力欄ごとに用意するTextFormFieldにvalidatorを書く- 送信時に
_formKey.currentState?.validate()を呼ぶ dispose()でcontrollerを破棄する
TextEditingControllerを使う理由
入力値を送信時に読むだけなら onSaved でも構いません。ただ、入力中の文字数表示、検索欄のクリア、初期値の反映、別Widgetとの連携が必要になると、TextEditingController を使った方が扱いやすくなります。
注意点
- StatefulWidgetでcontrollerを作ったら、基本的に
dispose()する - buildメソッド内で毎回controllerを作らない
- 入力値は
trim()してから保存やAPI送信に使う - フォームが大きくなったら、入力状態と保存処理を別クラスへ分ける
あわせて読みたい
- FlutterでAPI通信をRepositoryに分けてFutureBuilderで表示する方法
- LaravelでAPI ResourceとValidationを使ってJSON APIを整える方法
- JavaScriptでフォーム入力をリアルタイムに検証する方法
- Codex・Claude Code・ChatGPTを使い分けてWordPressを開発する方法