INDEX / JOURNAL / LOG-009
VOL. 2026 · ENGINEERING
SERIES 2 / 8
LOG-009 · FORM & DIALOG

入力を受け取り、結果を返す

PUBLISHED
2026 · 08 · 07
AUTHOR
MIGIWAYA
READ
約 5 分
TAGS
#flutter#dart

§ 01CONTROLLER

lib/screens/profile_edit_screen.dartDART
class _ProfileEditScreenState extends State<ProfileEditScreen> {
final _nameController = TextEditingController();
 
@override
void dispose() {
_nameController.dispose(); // 忘れると解放されずに残る
super.dispose();
}
 
@override
Widget build(BuildContext context) {
return TextField(controller: _nameController);
}
}

§ 02FORM

lib/screens/profile_edit_screen.dartDART
final _formKey = GlobalKey<FormState>();
 
Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
children: [
TextFormField(
controller: _nameController,
decoration: const InputDecoration(labelText: '表示名'),
validator: _validateName,
),
const SizedBox(height: 16),
ElevatedButton(onPressed: _submit, child: const Text('保存')),
],
),
)
DART
void _submit() {
if (!_formKey.currentState!.validate()) return; // 落ちたら送らない
// ここから先は、全項目が検証を通っている
}

§ 03VALIDATOR

lib/screens/profile_edit_screen.dartDART
String? _validateName(String? value) {
final name = value?.trim() ?? '';
if (name.isEmpty) return '表示名を入力してください';
if (name.length > 20) return '20 文字以内で入力してください';
return null; // null が「問題なし」
}
test/unit/validate_name_test.dartDART
test('空文字はエラーメッセージを返す', () {
expect(validateName(''), isNotNull);
expect(validateName('みぎわ'), isNull);
});

§ 04FOCUS

DART
TextFormField(
controller: _nameController,
textInputAction: TextInputAction.next,
onFieldSubmitted: (_) => FocusScope.of(context).nextFocus(),
)

§ 05DIALOG

lib/widgets/confirm_dialog.dartDART
Future<bool?> confirmDelete(BuildContext context) {
return showDialog<bool>(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
title: const Text('この項目を削除しますか'),
content: const Text('削除すると元に戻せません。'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('キャンセル'),
),
TextButton(
onPressed: () => Navigator.pop(context, true),
child: const Text('削除'),
),
],
),
);
}

§ 06RESULT

lib/screens/stock_detail_screen.dartDART
Future<void> _onDeletePressed() async {
final confirmed = await confirmDelete(context);
if (confirmed != true) return; // null も「実行しない」に倒す
if (!context.mounted) return; // await をまたいだので確認する
 
await _repository.delete(item.id);
if (!context.mounted) return;
Navigator.pop(context); // 削除できたので一覧へ戻る
}

§ 07SUMMARY

脚注 · NOTES
  1. [1]
  2. [2]
  3. [3]
  4. [4]
  5. [5]
同シリーズ · Flutter の基礎を実コードで学ぶ II
§ + RELATED すべて見る →
INQUIRY
CONTACT
LOCATION
STATUS
Active / Open
ESTABLISHED
2024 · 5 · 5
FORM