일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- appbar
- 앱
- binding
- ScrollView
- intent
- 테스트
- Kotlin
- android
- textfield
- Coroutines
- DART
- scroll
- Dialog
- tabbar
- CustomScrollView
- textview
- LifeCycle
- TEST
- activity
- 안드로이드
- data
- Flutter
- Button
- livedata
- drift
- 앱바
- viewmodel
- Compose
- 계측
- Navigation
- Today
- Total
Study Record
[Flutter] Form + TextFormField - 한번에 입력 값 관리하기, errorText, border 본문
[Flutter] Form + TextFormField - 한번에 입력 값 관리하기, errorText, border
초코초코초코 2023. 3. 3. 21:59✍ TextFormField Widget
TextFormField 위젯은 TextField 에서 몇개의 기능이 추가된 위젯이다. 따라서, TextField 에서 사용하는 인자값을 거의 그대로 사용할 수 있다. 또한, TextFormField 에는 사용자가 입력한 입력 값을 검증해 정해진 오류에 맞는 text를 보여줄 수 있다.(validator)
TextFormField 와 Form 위젯을 함께 사용하면 여러개의 입력값을 한번에 관리할 수 있다. 바로 예시를 들면,
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: HomeScreen()));
class HomeScreen extends StatefulWidget {
HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final GlobalKey<FormState> formKey = GlobalKey();
String? text1 = "";
String? text2 = "";
String? text3 = "";
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CustomTextFormField(onSavedEvent: (String? val) { text1 = val; }),
CustomTextFormField(onSavedEvent: (String? val) { text2 = val; }),
CustomTextFormField(onSavedEvent: (String? val) { text3 = val; }),
ElevatedButton(
onPressed: onCheckPress,
child: const Text("check 버튼"),
),
Text("$text1 , $text2 , $text3")
],
),
),
),
);
}
void onCheckPress() {
if (formKey.currentState == null) {
return;
}
setState(() {
if (formKey.currentState!.validate()) {
// 오류가 없는 경우
formKey.currentState!.save();
} else {
text1 = "";
text2 = "";
text3 = "";
}
});
}
}
class CustomTextFormField extends StatelessWidget {
final FormFieldSetter<String>? onSavedEvent;
const CustomTextFormField({required this.onSavedEvent, Key? key})
: super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: TextFormField(
onSaved: onSavedEvent,
validator: (String? val) {
if (val == null || val.isEmpty) {
return "값을 입력해주세요.";
}
if (val.contains("사과")) {
return "\"사과\"는 금지어입니다.";
}
return null;
},
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16.0),
borderSide: BorderSide(width: 2, color: Colors.black87)
),
),
)
);
}
}
예시 코드에 대해 설명하면,
Form 의 key 인자에 FormState 타입을 가진 GlobalKey 를 넣으면 이 키로 Form 의 자식 위젯의 TextFormField 를 전부 컨트롤할 수 있다.
😶 validate()
GlobalKey 의 currentState.validate(); 함수를 호출하면 키를 소유한 Form 위젯의 하위 TextFormField 위젯의 validator 를 전부 호출한다. 각 TextFormField 의 validator 의 리턴값이 전부 null 이면 true , 하나라도 null 이 아니면 false 이 리턴된다. 이 과정에서 TextFormField 는 validator 의 리턴값이 null 이 아니면 error 상태가 되고 return 값의 String 으로 errorText 가 보여진다.
final GlobalKey<FormState> formKey = GlobalKey();
// TextFormField 의 validator 를 호출하고 전부 다 null 을 리턴받으면 true 그렇지 않으면 false 을 리턴한다.
formKey.currentState!.validate();
// Form 예시
Form(
key: formKey,
child: Column(
children: [
TextFormField(
validator: (String? val) {
if (val == null || val.isEmpty) {
return "값을 입력해주세요.";
}
return null;
},
),
TextFormField(
validator: (String? val) {
if (val == null || val.isEmpty) {
return "값을 입력해주세요.";
}
return null;
},
),
]
),
)
😶 save()
validate() 와 비슷하게 currentState.save(); 함수를 실행하면 관련된 TextFormField 전체의 onSaved 가 호출된다. 따라서 입력값을 한 번에 받아서 정리할 때 유용하다.
final GlobalKey<FormState> formKey = GlobalKey();
String? text1;
String? text2;
// TextFormField 의 onSaved 를 호출한다.
formKey.currentState!.save();
// 예시 Form
Form(
key: formKey,
child: Column(
children: [
TextFormField(
onSaved: (String? val) {
text1 = val;
},
),
TextFormField(
onSaved: (String? val) {
text2 = val;
},
),
]
),
)
😶 validate() + save()
앞의 두 기능을 적절히 사용하면, validate() 로 한번에 TextFormField 의 입력값을 검증하고 true 를 반환하면(오류가 없으면) save() 를 통해 데이터를 한번에 가져오는 흐름이 가능하다.
final GlobalKey<FormState> formKey = GlobalKey();
// TextFormField 입력값 검증
if (formKey.currentState!.validate()) {
// 오류가 없는 경우
formKey.currentState!.save();
}
😶 validator 의 리턴값이 null이 아닐 경우 errorText, errorStyle
TextFormField 의 validator 이 호출되고 입력값에 오류가 있어 오류 관련 String 을 리턴할 경우 그 값이 errorText 로 보여지게 되는데 error 상태일 때, TextFormField 의 border 값과 textStyle 값을 InputDecoration 으로 설정할 수 있다.
TextFormField(
...
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16.0),
borderSide: BorderSide(width: 2, color: Colors.black87)
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16.0),
borderSide: BorderSide(width: 2, color: Colors.black87)
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16.0),
borderSide: BorderSide(width: 2, color: Colors.pinkAccent)
),
errorStyle: TextStyle(color: Colors.pinkAccent, fontWeight: FontWeight.bold)
);
border 값은 errorBorder 값으로 에러 텍스트 글자 스타일은 errorStyle 로 설정할 수 있다. 단, errorBorder 값이 null 아 아니면 border 값도 null 아 아니여야 한다. errorBorder != null && border == null 일 경우 error 상태일때 해당 errorBorder 로 바뀌지 않을 수 있다.
+ TextFormField 의 border 종류
인자 | 설명 |
border | 기본 border |
focusBorder | focus 가 있는 상태 |
errorBorder | error 상태에서 focus 가 없는 상태 |
focusErrorBorder | error 상태에서 focus 가 있는 상태 |
enabledBorder | 사용 가능 상태 |
disabledBorder | 사용 불가 상태 |
TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16.0),
borderSide: BorderSide(width: 2, color: Colors.black87)
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16.0),
borderSide: BorderSide(width: 2, color: Colors.black87)
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16.0),
borderSide: BorderSide(width: 2, color: Colors.deepPurple)
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16.0),
borderSide: BorderSide(width: 2, color: Colors.green)
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16.0),
borderSide: BorderSide(width: 2, color: Colors.red)
),
),
);
😶 autovalidateMode
Form 의 인자 중 autovalidateMode : AutovalidateMode.always 로 하면 사용자가 입력 폼에 입력할 때마다 관련 입력 폼 전체 validate 를 호출한다.
Form(
key: formKey,
autovalidateMode: AutovalidateMode.always,
child: Column(
children: [
TextFormField(
onSaved: (String? val) {
text1 = val;
},
),
TextFormField(
onSaved: (String? val) {
text2 = val;
},
),
]
),
)
'Flutter > widget_TextField' 카테고리의 다른 글
[Flutter/TextField] 비밀번호 입력 설정 (0) | 2023.03.31 |
---|---|
[Flutter/TextField] 입력 폼 border (0) | 2023.03.31 |
[Flutter] 입력 받기 (TextField) (0) | 2023.02.25 |
[Flutter/TextField] 키보드 액션 버튼 값 바꾸기 (textInputAction) (0) | 2023.02.25 |
[Flutter/TextField] decoration, text, hint (0) | 2023.02.24 |