やりたいこと
テキスト入力の項目で、以下のように必須エラーなどのバリデーションメッセージを出しているが、メッセージを項目ごとに定義せずに、「〜は必須です」の1種類だけを登録し、「〜」部分に項目名を埋め込みたい。
バリデーションで固定のメッセージを表示すること自体は、すでに以下を参考にさせていただき、「form_field_validator」を利用して、できている状態です。
自分で、元のValidatorを継承したValidatorをつくる
ChatGPTさんに相談しながら解決した方法です。もしかするともっと良い方法があるのかもしれないですが・・・。
例えば、RequiredValidatorのエラーメッセージに項目名を埋め込みたい場合は、RequiredValidatorを継承して、コンストラクタの引数に項目名を取る、自作のValidatorを作成しました。
///必須バリデータ(項目名をエラーメッセージに埋め込む)
class CustomRequiredValidator extends RequiredValidator {
final String filedName;
CustomRequiredValidator(
{String errorText = 'この項目は必須です', required this.filedName})
: super(errorText: '$filedName は必須です');
}
「form_field_validator」のライブラリで定義されている「RequiredValidator」のソースを見ると、isValidでない場合は、以下のようにerrorTextを返しているので、errorTextに項目名を埋め込んだメッセージを渡すことで、うまく埋め込まれているようです。
※RequiredValidatorのソース
class RequiredValidator extends TextFieldValidator {
RequiredValidator({required String errorText}) : super(errorText);
@override
bool get ignoreEmptyValues => false;
@override
bool isValid(String? value) {
return value!.isNotEmpty;
}
@override
String? call(String? value) {
return isValid(value) ? null : errorText;
}
}
他のバリデータと組み合わせる
本来は、必須かつ200文字以内というバリデーションをかけたかったため、同様にMaxLengthValidatorを継承して、CustomMaxLengthValidatorというものも作り、
これらを囲んだMultiValidatorを返すメソッドを新しいクラスの中に作りました。(今思うと、customMultiValidatorではなく、normalTextValidatorのような名前の方がよかったかもしれません。)
///通常の必須テキスト項目用バリデータ(必須、200文字以内)
class CustomValidators {
static MultiValidator customMultiValidator({required String fieldName}) {
return MultiValidator([
CustomRequiredValidator(filedName: fieldName),
CustomMaxLengthValidator(filedName: fieldName, max: 200)
]);
}
}
呼び出す
この新しく作ったcustomMultiValidatorを、TextFormFieldのvalidatorの値として呼び出します。「fieldName」にメッセージに埋め込みたい項目名を設定します。
TextFormField(
decoration:
const InputDecoration(labelText: 'メールで受信した「共有ID」を入力'),
onChanged: (String value) {
setState(() {
listId = value;
});
},
validator: CustomValidators.customMultiValidator(
fieldName: '共有ID'),
),
)