[Flutter] TextFormField & Form

Jinno·2023년 1월 14일
0

Flutter

목록 보기
15/19

TextField에서 onChanged로 입력을 관리 시, 여러개의 TextField가 있으면 하나하나 처리해줘야 함. TextFormField를 사용하면 한 번에 처리를 할 수 있음

정리

  1. Form은 아래에 있는 모든 TextFormField 컨트롤 가능
  2. 이를 위한 컨트롤러 역할을 formKey가 수행
  3. TextFormField의 validator로 error 조건 설정
  4. 버튼이 눌릴 때, formKey.currentState로 여러가지 처리
  5. formKey.currentState.validate() 에러 확인
  6. 에러가 없으면 formKey.currentState.save()로 값 일괄 저장
    -- formKey.currentState.save()를 호출하면 각 TextFormField의 onSaved가 호출 됨

TextFormField & Form

  1. TextField를 TextFormField Widget으로 변경
  2. validator 추가
    -- validator가 null을 리턴하면 에러가 없음을 의미
    -- string을 리턴하면 에러가 있음을 의미하고, TextFormField UI 아래에 해당 메시지를 자동으로 표시해줌
TextFormField renderTextFiled() {
    return TextFormField(
      validator: (String? val) {
        if (val == null || val.isEmpty) {
          return '값을 입력하세요';
        }
        return null;
      },
      cursorColor: Colors.grey,
      maxLines: isTime ? 1 : null,
      expands: !isTime,
      keyboardType: isTime ? TextInputType.number : TextInputType.multiline,
      inputFormatters: isTime ? [FilteringTextInputFormatter.digitsOnly] : [],
      decoration: InputDecoration(
        border: InputBorder.none,
        filled: true,
        fillColor: Colors.grey[300],
      ),
    );
  }
  1. 해당 TextFormField Widget들을 Form으로 묵어주기
    --꼭 바로 위에서 묶어주지 않아도 됨

  2. Form에 key를 추가
    -- final GlobalKey formKey = GlobalKey();
    -- key: formKey

  3. key값을 받아서 전체 처리
    -- 아래에서는 Button Widget onPressed에서 처리
class FormForm extends State<ScheduleBottomSheet> {
  final GlobalKey<FormState> formKey = GlobalKey();

  
  Widget build(BuildContext context) {
    return Container(
      child: Form(
        key: formKey,
		//autovalidateMode: AutovalidateMode.always,
        child: Column(
          children: [
            CustomTextFiled(label: '시작 시간', isTime: true),
            CustomTextFiled(label: '시작 시간', isTime: true),
            _SaveButton(onPressed: onSavePressed),
          ],
        ),
      ),
    );
  }

  void onSavePressed() {
    // formKey는 생성했으나, From Widget과 결합이 안된 상태
  // 위에서는 key: formKey로 연결을 해주고 있음
  // 다른 동료가 삭제할 가능성도 있기에, 추가
    if (formKey.currentState == null) {
      return;
    }
	
  // 위에서 null check가 되어서, null일 수 없기에 formKey.currentState!
    if (formKey.currentState!.validate()) {
      print('에러가 없습니다.');
    } else {
      print('에러!!!!!!');
    }
  }
}

TextFormField Save

  • formKey.currentState.save()로 값 일괄 저장
  • formKey.currentState.save()를 호출하면 각 TextFormField의 onSaved가 호출 됨

TextFormField에 onSaved 설정

class MyTextFormFiled extends StatelessWidget {  
  final FormFieldSetter<String> onSaved;
  const CustomTextFiled({
    Key? key,    
    required this.onSaved,
  }) : super(key: key);

  
  Widget build(BuildContext context) {
    return Column(      
      children: [        
        TextFormField(onSaved: onSaved),
        TextFormField(onSaved: onSaved),
      ],
    );
  }
}
profile
Innovation, 기록용

0개의 댓글