3

検証後に Flutter フォームからエラーのあるフィールドのリストを取得できますか? これは、開発者がフォーカス ノードを使用して、エラーのあるフィールドに注意を向け直すのに役立ちます。

4

2 に答える 2

4

Guillaume の回答を拡張して、機能を再利用可能なクラスにラップしました。

ここで DartPad の実際の例を見ることができます: https://www.dartpad.dev/61c4ccddbf29a343c971ee75e60d1038

import 'package:flutter/material.dart';

class FormValidationManager {
  final _fieldStates = Map<String, FormFieldValidationState>();

  FocusNode getFocusNodeForField(key) {
      _ensureExists(key);

      return _fieldStates[key].focusNode;
  }

  FormFieldValidator<T> wrapValidator<T>(String key, FormFieldValidator<T> validator) {
      _ensureExists(key);

      return (input) {
          final result = validator(input);

          _fieldStates[key].hasError = (result?.isNotEmpty ?? false);

          return result;
      };
  }

  List<FormFieldValidationState> get erroredFields =>
      _fieldStates.entries.where((s) => s.value.hasError).map((s) => s.value).toList();

  void _ensureExists(String key) {
      _fieldStates[key] ??= FormFieldValidationState(key: key);
  }

  void dispose() {
    _fieldStates.entries.forEach((s) {
        s.value.focusNode.dispose();
    });
  }
}

class FormFieldValidationState {
  final String key;

  bool hasError;
  FocusNode focusNode;

  FormFieldValidationState({@required this.key})
      : hasError = false,
      focusNode = FocusNode();
}

これを使用するには、通常どおりフォームを作成しますがFormValidationManager、状態クラスに を追加し、そのインスタンスを使用して検証メソッドをラップします。

使用法:

class _MyWidgetState extends State<MyWidget> {
  final _formKey = GlobalKey<FormState>();
  final _formValidationManager = FormValidationManager();

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        children: [
          TextFormField(
              focusNode: _formValidationManager.getFocusNodeForField('field1'),
              validator: _formValidationManager.wrapValidator('field1', (value) {
                if (value.isEmpty) {
                  return 'Please enter a value';
                }

                return null;
              })),
          TextFormField(
              focusNode: _formValidationManager.getFocusNodeForField('field2'),
              validator: _formValidationManager.wrapValidator('field2', (value) {
                if (value.isEmpty) {
                  return 'Please enter a value';
                }

                return null;
              })),
          ElevatedButton(
              onPressed: () {
                if (!_formKey.currentState.validate()) {
                  _formValidationManager.erroredFields.first.focusNode.requestFocus();
                }
              },
              child: Text('SUBMIT'))
        ],
      ),
    );
  }

  @override
  void dispose() {
    _formValidationManager.dispose();
    super.dispose();
  }
}
于 2021-07-22T23:52:43.850 に答える