Flutter 入力エラー 表示は、Formで入力欄をまとめ、TextFormFieldのvalidatorで条件を決め、送信時にvalidate()を呼び出すと実装できます。入力が空なら「入力してください」のようなメッセージを表示し、問題がなければ保存やAPI送信へ進めます。
この記事では、名前入力を例に、最小構成のコード、入力中にエラーを表示する方法、エラーが出ないときの確認点まで説明します。
初心者の疑問: TextFieldを使っているのに、なぜ入力エラーが表示されないのでしょうか?
Flutterの入力エラー表示に使う3つの部品
まず、役割を分けて考えると理解しやすくなります。
| 部品 | 役割 |
|---|---|
Form | 複数の入力欄をまとめて管理する |
TextFormField | 入力欄と検証ルールを持つ |
validator | 入力が正しいか判定し、エラー文またはnullを返す |
TextFieldにも見た目のエラー表示機能はありますが、フォーム全体をまとめて検証するならTextFormFieldの方が扱いやすい構成です。Flutter公式のフォーム検証でも、この組み合わせが使われています。
validatorはエラーがあるときに文字列を返し、問題がないときは必ずnullを返します。
最小構成で入力エラーを表示する
次の例では、名前が空のまま「送信」ボタンを押すと、入力欄の下にエラーメッセージを表示します。
import 'package:flutter/material.dart';
class ProfileForm extends StatefulWidget {
const ProfileForm({super.key});
@override
State<ProfileForm> createState() => _ProfileFormState();
}
class _ProfileFormState extends State<ProfileForm> {
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextFormField(
decoration: const InputDecoration(
labelText: '名前',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.trim().isEmpty) {
return '名前を入力してください';
}
return null;
},
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('入力内容を確認しました')),
);
}
},
child: const Text('送信'),
),
],
),
);
}
}
コードの流れ
GlobalKey<FormState>を作り、フォームの状態を参照できるようにします。Formにkey: _formKeyを指定します。TextFormFieldのvalidatorで入力条件を決めます。- ボタンで
_formKey.currentState!.validate()を呼び出します。 trueなら保存や送信、falseならエラー表示のまま止めます。
validate()を呼ぶと、同じForm内にある各フィールドのvalidatorが実行されます。エラーが1つでもあればfalseになり、該当するメッセージが画面に表示されます。
初心者の疑問: validatorを書いただけで検証されますか? validatorは判定ルールを登録するだけです。送信ボタンなどからvalidate()を呼ぶことで、実際の検証とエラー表示が始まります。
よく使う入力チェックの書き方
空欄を禁止する
空文字だけでなく、前後に空白しかない入力も拒否したい場合はtrim()を使います。
validator: (value) {
if (value == null || value.trim().isEmpty) {
return '入力してください';
}
return null;
},
メールアドレスの形式を確認する
複雑な正規表現を最初から作るより、まずは「空欄ではない」「@を含む」程度の簡単な条件から始めると、初心者でも調整しやすくなります。
validator: (value) {
final email = value?.trim() ?? '';
if (email.isEmpty) {
return 'メールアドレスを入力してください';
}
if (!email.contains('@')) {
return 'メールアドレスの形式を確認してください';
}
return null;
},
注意: 画面上の入力チェックだけで、メールアドレスの存在や本人確認まで保証できるわけではありません。サーバー側でも必要な検証を行ってください。
文字数に上限を設ける
validator: (value) {
final text = value?.trim() ?? '';
if (text.isEmpty) {
return 'コメントを入力してください';
}
if (text.length > 200) {
return '200文字以内で入力してください';
}
return null;
},
日本語を含む入力では、必要に応じてcharactersパッケージなど、ユーザーが認識する文字単位での数え方も検討します。単純なlengthが要件に合うかは、アプリの仕様を確認してください。
入力中にエラーを表示する方法
初期状態では、送信ボタンを押すまでエラーを表示しない設計が自然です。一方で、入力を始めた後はすぐに間違いを知らせたい場合、autovalidateModeを設定できます。
Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
children: [
TextFormField(
validator: (value) {
if (value == null || value.trim().isEmpty) {
return '名前を入力してください';
}
return null;
},
),
],
),
)
AutovalidateMode.onUserInteractionは、ユーザーが操作した後に自動検証する設定です。画面を開いた直後から赤いエラーを並べるより、入力を始めてから知らせる方が、フォームの印象が分かりやすくなります。
比較ポイント: 送信時だけ検証する方法は落ち着いて入力できます。入力中に検証する方法は間違いに早く気づけます。入力項目の重要度や画面の長さに合わせて選びましょう。
入力エラーが表示されないときの確認点
`TextField`ではなく`TextFormField`を使っているか
validatorはTextFormFieldに指定します。TextFieldを使い続ける場合は、errorTextを状態変数で管理する別の実装が必要です。
`Form`と入力欄が同じ階層にあるか
TextFormFieldが対象のFormの子孫になっていなければ、そのフォームのvalidate()で検証されません。Formの中にTextFormFieldを置いているか確認します。
ボタンで`validate()`を呼んでいるか
ボタンのonPressedが空だったり、別のキーを参照していたりすると、エラー表示は始まりません。
失敗例: build()の中で毎回GlobalKey<FormState>()を作ると、ボタンを押したときにフォームとキーの対応が崩れることがあります。 改善例: Stateクラスのフィールドとしてfinal _formKey = GlobalKey<FormState>();を1回だけ作り、build()では同じキーを使います。
`validator`が常に`null`を返していないか
条件分岐の後に必ずreturn nullがあるか、入力値を確認しています。例えば、次のコードでは常に問題なしと判定されます。
validator: (value) {
return null;
},
複数の入力欄を検証する場合
メールアドレスとパスワードのように入力欄が複数ある場合も、同じFormの中にTextFormFieldを追加します。送信時のvalidate()は、それぞれのvalidatorを順番に実行します。
パスワードの確認欄など、2つの値を比較する場合は、TextEditingControllerで入力値を取得してから比較します。ただし、比較処理が複雑になったら、検証ロジックを別メソッドに分けると読みやすくなります。
チェックリスト: Formにキーを指定した、入力欄はTextFormFieldにした、空欄時のメッセージを書いた、validate()を送信処理の前に呼んだ、成功時だけ保存する流れにした。
関連記事と次にやること
入力欄そのものの作り方を先に確認したい場合は、Flutterでフォーム入力を実装する方法も参考になります。今回の検証処理を追加したら、次はTextEditingControllerで値を取得し、実際の保存処理につなげてみましょう。
次にやること: まず名前欄を1つ作り、空欄で送信したときにエラーメッセージが表示されることを確認してください。
まとめ
Flutterの入力エラー表示は、Form、TextFormField、validator、validate()の4点を組み合わせると実装できます。最初は空欄チェックだけで動かし、必要に応じてメール形式や文字数、入力中の自動検証を追加すると安全です。
入力チェックが動かないときは、TextFormFieldが対象のForm内にあるか、同じGlobalKeyでvalidate()を呼んでいるか、validatorがエラーメッセージを返しているかを順番に確認しましょう。
コメント