0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Flutterで汎用的なバリデーション基盤を作る

Last updated at Posted at 2025-05-17

はじめに

Flutterでのフォームバリデーションの基盤を作成してみました。
バリデーションルール(ValidationRule)とバリデーター(Validator)を定義し、
各入力に対してルールを通じて検証(validate)する仕組みを実装しています。

見出し

  • Validationの基盤を作成する流れ
    1. Validation rulesを作成
    2. 基盤となるValidatorを作成
    3. 作成したValidation rulesを使用し、TextField専用のValidatorを作成

参考コード

Validationの基盤を作成する流れ

Validation rulesを作成

core/validation/rules配下にバリデーションルールを作成していきます。
※ 今回の例として、2つのValidation ruleを作成します。
※ 新たにルールが必要な場合は、core/validation/rules配下に追加してください。

abstractを使用して、Validation ruleで共通となるインターフェイスを作成します。

validatoinRule.dart
abstract class ValidationRule {
  String? validate(String value);
  String get errorMessage;
}

「必須」ルールとして、RequiredRuleを実装します。

ValidationRuleインターフェースをimplementsして、RequiredRuleクラスを作成します。

required_rule.dart
class RequiredRule implements ValidationRule {
  @override
  String? validate(String value) {
    return value.trim().isEmpty ? errorMessage : null;
  }

  @override
  String get errorMessage => '入力してください';
}

文字数制限ルールとして、LengthRuleを実装します。

RequiredRuleと同様に、ValidationRuleインターフェースをimplementsして、LengthRuleクラスを作成します。

length_rule.dart

class LengthRule implements ValidationRule {
  final int? maxLength;
  final int? minLength;

  const LengthRule({this.maxLength, this.minLength});

  @override
  String? validate(String value) {
    final trimmed = value.trim();
    if (maxLength != null && trimmed.length > maxLength!) {
      return '$maxLength文字以内で入力してください';
    }
    if (minLength != null && trimmed.length < minLength!) {
      return '$minLength文字以上で入力してください';
    }
    return null;
  }

  @override
  String get errorMessage => '文字数制限を超えています';
}

基礎のValidatorを作成


class Validator<T> {
  final List<ValidationRule> rules;

  const Validator(this.rules);

  String? validate(T value) {
    for (final rule in rules) {
      final error = rule.validate(value.toString());
      if (error != null) return error;
    }
    return null;
  }

  /// 指定された型のルールを取得
  R? getRule<R extends ValidationRule>() {
    for (final rule in rules) {
      if (rule is R) {
        return rule;
      }
    }
    return null;
  }
}

作成したValidation rulesを使用し、TextField専用のValidatorを作成

Validatorクラスを継承してTextFieldValidatorを作成します。
Validation rulesは、TextFieldValidatorのコンストラクタ時に、super([...])を使用して親クラスのValidatorに渡します。


class TextFieldValidator extends Validator<String> {
  TextFieldValidator({int? maxLength, int? minLength, bool required = true})
    : super([
        if (required) RequiredRule(),
        if (maxLength != null || minLength != null)
          LengthRule(maxLength: maxLength, minLength: minLength),
      ]);

  int? get maxLength => getRule<LengthRule>()?.maxLength;
  int? get minLength => getRule<LengthRule>()?.minLength;

  @override
  String? validate(String value) {
    final trimmed = value.trim();
    return super.validate(trimmed);
  }
}


最後に

汎用的なValidationを作成してみました。
まだまだ改善が必要ようそうなので、更新していきたいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?