본문 바로가기
Flutter

[Flutter] Widget(6) - Form

by 아마도개발자 2023. 12. 12.

 

Form Widget
  • Form 위젯은 여러 FormField 위젯을 그룹화할 수 있는 위젯이다. (e.g. TextField widgets).
  • 각각의 form field는 FormField 위젯으로 감싸져 있어야 한다. 
  • 각각의 FormField의 저장, 초기화, 검증은 FormState에서 메서드를 호출하여 이루어진다.
  • FormState를 가질려면 Form.of를 사용하거나 조상이 Form인 context에서 GlobalKey를 Form 생성자에 전달하고, GlobalKey.currentState를 호출할 수 있다.

 

 

Form 예제 코드
  • TextFormField의 input 값을 검증한 후, submit하는 코드 예제
import 'package:flutter/material.dart';

void main() => runApp(const FormExampleApp());

class FormExampleApp extends StatelessWidget {
  const FormExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Form Sample')),
        body: const FormExample(),
      ),
    );
  }
}

class FormExample extends StatefulWidget {
  const FormExample({super.key});

  @override
  State<FormExample> createState() => _FormExampleState();
}

class _FormExampleState extends State<FormExample> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  String? emailValidateCheck(String? email) {
    if (email == null || email.isEmpty) return "검증 실패";
    return null;
  }

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          TextFormField(
            decoration: const InputDecoration(
              hintText: 'Enter your email',
            ),
            validator: emailValidateCheck;
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 16.0),
            child: ElevatedButton(
              onPressed: () {
                // Validate will return true if the form is valid, or false if
                // the form is invalid.
                if (_formKey.currentState!.validate()) {
                  // Process data.
                }
              },
              child: const Text('Submit'),
            ),
          ),
        ],
      ),
    );
  }
}

 

우선 TextFormField에서 validato인자에 emailValidateCheck라는 유효성검사 함수를 넘겨주면 button에서 _formkey.currentState!.validate() 메쏘드가 호출될 때, emailValidateCheck가 실행되어 유효성 검사가 발생하게 된다.

_formkey.currentState!.validate() 호출 시 emailValidateCheck가 실행되는 이유는 form.dart에서 _validate 메써드를 확인해보면 이유를 알 수 있다.

bool _validate() {
    bool hasError = false;
    for (final FormFieldState<dynamic> field in _fields) {
      hasError = !field.validate() || hasError;
    }
    return !hasError;
  }

 

각 field에서 호출되는 field.validate()를 다시 확인해 보면 

void _validate() {
    if (widget.validator != null) {
      _errorText.value = widget.validator!(_value);
    }
  }

 

widget.validator가 실행되고 있음을 눈으로 확인할 수 있다.

 

  • emialValidateCheck 실행 화면

빈 칸을 입력하여 유효성 검사 실패, 검증 실패를 return