Flutter - Form Validation
2022. 7. 13. 12:48ㆍDEV/Flutter
반응형
사용 위젯
- Form
- TextFormField
TextField 위젯을 사용하면 TextEditingController 를 사용해야하는데, 여러 개의 필드 사용 시 관리가 어려워진다. 그래서 TextFormField 를 사용한다. 그럼 바로 시작해보자.
1. Form 생성
Form 위젯을 생성하고 key 값을 지정한다.
- key : GlobalKey() 지정
- child : TextFormField 위젯 추가 예정
class FormScreen extends StatefulWidget {
const FormScreen({Key? key}) : super(key: key);
@override
State<FormScreen> createState() => _FormScreenState();
}
class _FormScreenState extends State<FormScreen> {
// * Form GlobalKey
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Form(
key: _formKey, // * GlobalKey
child: Column(
children: const [
// * TextFormField
],
),
);
}
}
2. TextFormField Refactoring
기본적으로 Form에서 사용하는 TextFormField의 공통 설정들이 있는데 모든 필드에 직접 속성을 설정해서 사용하면 유지 보수가 힘들어진다. 그래서 리팩토링을 해서 사용하는 걸 권장한다. Class로 선언해서 위젯으로 만들 수도 있고, 함수형으로 만들어서 위젯을 반환하는 방식으로 만들 수도 있다.
Class 방식
class MyFormField extends StatelessWidget {
final String hintText;
final IconData icon;
final FormFieldValidator? validator;
final FormFieldSetter? onSaved;
const MyFormField({
Key? key,
required this.hintText,
required this.icon,
this.validator,
this.onSaved,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return TextFormField(
decoration: InputDecoration(
prefixIcon: Icon(
icon,
color: Palette.iconColor,
),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Palette.textColor1),
borderRadius: BorderRadius.all(Radius.circular(35)),
),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Palette.textColor1),
borderRadius: BorderRadius.all(Radius.circular(35)),
),
hintText: hintText,
hintStyle: const TextStyle(
color: Palette.textColor1,
fontSize: 14,
),
contentPadding: const EdgeInsets.all(10), // * 높이 조절
),
validator: validator,
onSaved: onSaved,
autovalidateMode: AutovalidateMode.always, // * 필드별 자동 체크 모드 ON
);
}
}
Function 방식
myTextFormField({
required Key key,
required String hintText,
required IconData icon,
required FormFieldValidator validator,
required FormFieldSetter onSaved,
}) {
return TextFormField(
decoration: InputDecoration(
prefixIcon: Icon(
icon,
color: Palette.iconColor,
),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Palette.textColor1),
borderRadius: BorderRadius.all(Radius.circular(35)),
),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Palette.textColor1),
borderRadius: BorderRadius.all(Radius.circular(35)),
),
hintText: hintText,
hintStyle: const TextStyle(
color: Palette.textColor1,
fontSize: 14,
),
contentPadding: const EdgeInsets.all(10), // * 높이 조절
),
validator: validator,
onSaved: onSaved,
);
}
3. TextFormField 생성
- key : ValueKey() 지정
- validator : <FormFieldValidator> 타입의 validation 체크 함수 → 오류 시 오류 문구 출력
- onSaved : <FormFieldSetter> 타입의 value 저장 함수 → setState()
String name = '';
String email = '';
...
MyFormField( // * Class Refactoring
key: const ValueKey(1),
validator: (value) {
// * Check Validation
if (!RegExp(r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$').hasMatch(value)) {
return 'Please enter valid email adress';
}
return null;
},
onSaved: (value) {
// * Save value
setState(() {
password = value!;
});
},
hintText: 'Email',
icon: Icons.lock,
),
myTextFormField( // * Function Refactoring
key: const ValueKey(2),
validator: (value) {
// * Check Validation
if (value!.isEmpty || value.length < 6) {
return 'Password must be at least 7 characters long';
}
return null;
},
onSaved: (value) {
// * Save value
setState(() {
password = value!;
});
},
hintText: 'Password',
icon: Icons.lock,
),
...
4. Validaion 실행
- Validate Form:
if (_formKey.currentState!.validate()
- Save Values :
_formKey.currentState!.save()
- Auto Validation : TextFormField >
autovalidateMode: AutovalidateMode.onUserInteraction
→ 각 필드에 사용자가 입력하는 값의 변화에 따라 즉시 결과를 보여준다.
5. Example Code
import 'package:flutter/material.dart';
import 'package:mychat/config/palette.dart';
import 'package:mychat/screen/sign_screen.dart';
class FormScreen extends StatefulWidget {
const FormScreen({Key? key}) : super(key: key);
@override
State<FormScreen> createState() => _FormScreenState();
}
class _FormScreenState extends State<FormScreen> {
final _formKey = GlobalKey<FormState>();
String name = '';
String email = '';
String password = '';
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
MyFormField(
key: const ValueKey(1),
validator: (value) {
if (value!.isEmpty || value.length < 4) {
return 'Please enter at least 4 characters';
}
return null;
},
onSaved: (value) {
setState(() {
name = value!;
});
},
hintText: 'User name',
icon: Icons.account_circle,
),
const SizedBox(height: 8),
myTextFormField(
key: const ValueKey(2),
validator: (value) {
if (!RegExp(
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$')
.hasMatch(value)) {
return 'Please enter valid email adress';
}
return null;
},
onSaved: (value) {
setState(() {
email = value!;
});
},
hintText: 'Email',
icon: Icons.email,
),
const SizedBox(height: 8),
myTextFormField(
key: const ValueKey(3),
validator: (value) {
if (value!.isEmpty || value.length < 6) {
return 'Password must be at least 7 characters long';
}
return null;
},
onSaved: (value) {
setState(() {
password = value!;
});
},
hintText: 'Password',
icon: Icons.lock,
),
ElevatedButton(
onPressed: () {
// * 모든 Validation이 OK인 경우
if (_formKey.currentState!.validate()) {
// * 입력된 값들을 모두 저장
_formKey.currentState!.save();
}
},
child: const Text(
'Save',
style: TextStyle(
color: Colors.white,
),
),
),
],
),
);
}
}
myTextFormField({
required Key key,
required String hintText,
required IconData icon,
required FormFieldValidator validator,
required FormFieldSetter onSaved,
}) {
return TextFormField(
decoration: InputDecoration(
prefixIcon: Icon(
icon,
color: Palette.iconColor,
),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Palette.textColor1),
borderRadius: BorderRadius.all(Radius.circular(35)),
),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Palette.textColor1),
borderRadius: BorderRadius.all(Radius.circular(35)),
),
hintText: hintText,
hintStyle: const TextStyle(
color: Palette.textColor1,
fontSize: 14,
),
contentPadding: const EdgeInsets.all(10), // * 높이 조절
),
validator: validator,
onSaved: onSaved,
autovalidateMode: AutovalidateMode.onUserInteraction,
);
}
REF
🔗 [Blog]Form 으로 손쉽게 여러개의 텍스트필드 상태관리하기!
🔗 [YouTube] Form 으로 손쉽게 여러개의 텍스트필드 상태관리하기!
🔗 플러터(Flutter) 조금 매운맛 강좌 22 | 텍스트폼필드 validation 구현
반응형
'DEV > Flutter' 카테고리의 다른 글
Flutter & Firebase - iOS 오류 (0) | 2022.07.15 |
---|---|
Flutter & Firebase - Flutter multidex handling is disabled 오류 해결 방법 (0) | 2022.07.15 |
Flutter & Firebase Android SDK Version 오류 해결 (0) | 2022.07.15 |
Flutter 프로젝트에 Firebase 연동하기 (0) | 2022.07.13 |
What's new in Flutter 2022 (0) | 2022.07.06 |
VSCODE - Flutter Extension 및 추가 설정 (0) | 2022.06.29 |
Mac - Visual Studio Code에서 Flutter 설정 및 프로젝트 시작하기 (0) | 2022.06.25 |
Flutter Project 생성하기 (0) | 2022.06.25 |