본문 바로가기
Flutter

[Flutter] 로그인 유효성 체크하는 텍스트 폼 만들기

by 김무스비 2024. 12. 30.
728x90
반응형

오늘은 로그인 유효성을 체크하는 텍스트 폼 만드는 법을 탐구해보겠슴니다


1. Form 위젯 안에 TextFormField 위젯 만들기

Form위젯 안에 TextFormField위젯을 만들고, validator 프로퍼티에 유효성을 체크할 메서드를 넣어줍니다. 이때, (value)는 사용자가 입력할 값입니다. 여기서는 '이름' 영역에 입력된게 없으면 '이름을 입력하세요' 라는 문구가 뜨는 규칙을 적용했습니다.

//중략//
          TextFormField(
            decoration: const InputDecoration(labelText: '이름'),
            validator: (value) {
              if (value!.isEmpty) {
                return '이름을 입력하세요.';
              }
              return null;
            })
 

 

2. Form의 State 관리를 위한 Key를 생성하고 Form의 key프로퍼티에 해당 Key 넣어주기

Form에 입력되는 값들도 다 State와 관련이 있으므로, Form 위젯의 상태를 관리하고 제어하기 위한 Key를 만들어줍니다. 

formKey를 통해 수행할 수 있는 주요 역할은 다음과 같습니다.(by Chat GPT)

  1. 폼의 상태 관리: formKey를 사용하여 폼 위젯의 상태를 관리하고 유효성을 검사합니다. 폼의 상태를 가져오거나 변경하기 위해 currentState 속성을 사용할 수 있습니다.
  2. 유효성 검사: 폼의 유효성을 검사하기 위해 formKey.currentState.validate()를 호출하여 모든 하위 TextFormField의 validator를 실행합니다.
  3. 제출 처리: 폼이 제출되었을 때 처리를 수행하기 위해 formKey.currentState.save()를 호출하여 각 TextFormField의 onSaved 콜백을 실행합니다.
  4. 폼 리셋: 필요한 경우 폼을 리셋할 때 사용합니다. formKey.currentState.reset()을 호출하여 폼의 상태를 초기화할 수 있습니다.
//윗부분 생략//
final _formKey = GlobalKey<FormState>();
//중략//
 @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(children: <Widget>[
          TextFormField(
            decoration: const InputDecoration(labelText: '이름'),
            validator: (value) {
              if (value!.isEmpty) {
                return '이름을 입력하세요.';
              }
              return null;
            },
          ),
        ]),
      ),
    );
  }
}
 

 

3. 입력된 값을 저장할 변수를 만들고, TextFormField에 onSaved 프로퍼티에 추가해주기

onSaved 콜백은 사용자가 입력 필드에 값을 입력하고 폼이 제출될 때 실행됩니다. 이 때  입력된 값이 인자로 전달되고,  이때 위에서 선언한 _name 변수에 입력된 값이 저장됩니다.

//중략//
late String _name;
  late String _email;
//중략//
 TextFormField(
              decoration: const InputDecoration(labelText: '이름'),
              validator: (value) {
                if (value!.isEmpty) {
                  return '이름을 입력하세요.';
                }
                return null;
              },
              onSaved: (value) {
                _name = value!;
              },
            ),
//중략//

 

4.Form Key의 currentState를 통해 유효성을 검증하는 역할을 하는 버튼 만들기

위에서 언급한  formKey.currentState의 두 메서드 validate()와 save()를 통해 버튼 클릭시 모든 validator와 onSaved 콜백 함수를 실행하는 버튼을 만들어줍니다.  

이를 통해, 모든 validator에 대한 검증을 진행하고, 통과했다면 각 필드의 값을 위에서 생성한 변수에 저장하게 됩니다. 

아래의 코드는 최종적으로 그 결과를 print 해줍니다. 

   ElevatedButton(
              onPressed: () {
                if (_formKey.currentState!.validate()) {
                  _formKey.currentState!.save();
                  // 폼이 성공적으로 검증되었으므로 여기에서 추가 작업 수행
                  print('유효성 검사 통과 - 이름: $_name, 이메일: $_email');
                }
              },
              child: const Text('제출'),
            ),

 

5. 실제 구현 화면

제대로 입력하지 않았을 때

 

제대로 입력했을 때

제대로 입력했을때 debug console 화면


전체 소스코드

전체 소스코드

더보기
닫기

 

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('다중 TextFormField 예제'),
        ),
        body: const MyForm(),
      ),
    );
  }
}

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

  @override
  _MyFormState createState() => _MyFormState();
}

class _MyFormState extends State<MyForm> {
  final _formKey = GlobalKey<FormState>();
  late String _name;
  late String _email;

//중략//
  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          children: <Widget>[
            TextFormField(
              decoration: const InputDecoration(labelText: '이름'),
              validator: (value) {
                if (value!.isEmpty) {
                  return '이름을 입력하세요.';
                }
                return null;
              },
              onSaved: (value) {
                _name = value!;
              },
            ),
            const SizedBox(height: 20),
            TextFormField(
              decoration: const InputDecoration(labelText: '이메일'),
              validator: (value) {
                if (value!.isEmpty) {
                  return '이메일을 입력하세요.';
                }
                // 간단한 이메일 유효성 검사
                if (!value.contains('@')) {
                  return '올바른 이메일 주소를 입력하세요.';
                }
                return null;
              },
              onSaved: (value) {
                _email = value!;
              },
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                if (_formKey.currentState!.validate()) {
                  _formKey.currentState!.save();
                  // 폼이 성공적으로 검증되었으므로 여기에서 추가 작업 수행
                  print('유효성 검사 통과 - 이름: $_name, 이메일: $_email');
                }
              },
              child: const Text('제출'),
            ),
          ],
        ),
      ),
    );
  }
}

 

728x90
반응형