DevBoi

[Flutter] 다양한 FormBuilder,FormValidator 본문

[Mobile]/[Flutter]

[Flutter] 다양한 FormBuilder,FormValidator

HiSmith 2023. 8. 26. 18:40
반응형

다양한 폼 빌더를 구현했다.

사실 UI 와, 폼 빌더의 동작방식에 대한 내용인데. 어느 폼같이 비슷비슷하기때문에 정리용으로 작성한다.

 

폼은 formkey로 동작한다.

final _formKey = GlobalKey<FormBuilderState>();
@override
  Widget build(BuildContext context) {
    return  SingleChildScrollView(
      child: Column(
        children: <Widget>[
          FormBuilder(
            key: _formKey,
            // enabled: false,
            onChanged: () {
              _formKey.currentState!.save();
            },
            autovalidateMode: AutovalidateMode.disabled,
            initialValue: const {
              'gender': '상관없음'
            },
            skipDisabled: true,
            child:

위와 같이 선언하여 사용할 수 있고,

폼 빌더의 onChanged메소드와 연결하면, 해당 값이 변경될때마다 form 자체적으로 관리하는

state를 저장하게 된다.

  FormBuilderTextField(
              autovalidateMode: AutovalidateMode.always,
                name: 'title',
                decoration: InputDecoration(
                  labelText: '제목',
                ),
                onChanged: (val) {
                  setState(() {
                    _titleHasError =
                    !(_formKey.currentState?.fields['title']?.validate() ??
                        false);
                  });
                },
                validator: FormBuilderValidators.compose([
                  FormBuilderValidators.required(errorText: '제목은 필수 값 입니다.'),
                  FormBuilderValidators.max(20,errorText: '제목은 20자 이하여야 합니다.'),
                ]),
                keyboardType: TextInputType.number,
                textInputAction: TextInputAction.next,),

폼 텍스트 필드이다.

벨리데이터를 달면, 각 조건을 자동으로 검사해주는데,

기본으로 제공해주는 errorText도 있으나, 커스텀하게 다는게 좋다 (왜냐면 디폴트가 영어임)

 

FormBuilderDateTimePicker(
                  name: 'date',
                  initialEntryMode: DatePickerEntryMode.calendar,
                  initialValue: DateTime.now(),
                  inputType: InputType.both,
                  format: DateFormat("yyyy-MM-dd hh:mm"),
                  decoration: InputDecoration(
                    icon : const Icon(Icons.access_time,color: Colors.green,),
                    labelText: '시간',
                    suffixIcon: IconButton(
                      icon: const Icon(Icons.close),
                      onPressed: () {
                        _formKey.currentState!.fields['date']?.didChange(null);
                      },
                    ),
                  ),
                  initialTime: const TimeOfDay(hour: 8, minute: 0),
                  // locale: const Locale.fromSubtags(languageCode: 'fr'),
                ),

폼 날짜 피커이다.

이것도 뭐 사용방식은 비슷하다.

더많은 속성은 라이브러리 소스를 보면 바로 이해가 된다.

FormBuilderSlider(
                  name: 'slider',
                  validator: FormBuilderValidators.compose([
                    FormBuilderValidators.min(1,errorText: "인원수는 1명 이상이여야 합니다."),
                  ]),
                  onChanged: _onChanged,
                  min: 0.0,
                  max: 20.0,
                  initialValue: 2.0,
                  divisions: 20,
                  activeColor: Colors.green,
                  inactiveColor: Colors.green[100],
                  decoration: const InputDecoration(
                    icon: const Icon(Icons.people_alt_rounded,color: Colors.green,),
                    labelText: '인원 수',
                  ),
                ),

 

슬라이더이다.

인원에 대한 제한을 입력받는게 아니라, 슬라이더로 조정하도록 하고 싶어서 구현했다.

max값과 벨리데이터를 구현할 수 있다.

FormBuilderDropdown<String>(
                  name: 'gender',
                  decoration: InputDecoration(
                    icon: const Icon(Icons.back_hand_sharp,color: Colors.green,)
                  ),
                  items: genderOptions
                      .map((gender) => DropdownMenuItem(
                    alignment: AlignmentDirectional.center,
                    value: gender,
                    child: Text(gender),
                  ))
                      .toList(),
                  onChanged: (val) {
                    setState(() {
                      _genderHasError = !(_formKey
                          .currentState?.fields['gender']
                          ?.validate() ??
                          false);
                    });
                  },
                  valueTransformer: (val) => val?.toString(),
                ),

드롭다운 버튼이다.

List<String>을 아이템에 넣게 되면 해당 아이템들이 노출된다.

이렇게  표현이 가능하다.

  var genderOptions = ['남자', '여자', '상관없음'];

마지막에 해당 값을 String으로 바꿔야 json에 대한 관리가 가능하다.

FormBuilderFilterChip<String>(
                  autovalidateMode: AutovalidateMode.onUserInteraction,
                  decoration: const InputDecoration(
                      labelText: '소개 태그'),
                  name: 'introduce_tag',
                  selectedColor: Colors.white,
                  options: const [
                    FormBuilderChipOption(
                      value: '요금은 더치',
                    ),
                    FormBuilderChipOption(
                      value: '요금은 주최자',
                    ),
                    FormBuilderChipOption(
                      value: '게임하고 식사도',
                    ),
                    FormBuilderChipOption(
                      value: '게임만',
                    ),
                    FormBuilderChipOption(
                      value: '초보만',
                    ),
                    FormBuilderChipOption(
                      value: '고수만',
                    ),
                  ],
                  onChanged: _onChanged,
                )

태그에 대한 내용이다.

해당 태그는 체크와 체크해제를 할 수있다. 해당 값도 리스트 형태로 전달 된다.

 

마지막으로해당 값을 저장하기 위한 액션 버튼을 구현해야한다.

Row(
            children: <Widget>[
              Expanded(
                child: ElevatedButton(
                  onPressed: () {
                    if (_formKey.currentState?.saveAndValidate() ?? false) {
                      debugPrint(_formKey.currentState?.value.toString());
                    } else {
                      debugPrint(_formKey.currentState?.value.toString());
                      debugPrint('validation failed');
                    }
                  },
                  child: const Text(
                    '생성하기',
                    style: TextStyle(color: Colors.white),
                  ),
                ),
              ),
              const SizedBox(width: 20),
            ],

 

해당 같이하면, 폼에 있는 것을 키값으로 가져와서, value값을 확인할 수 있다.

즉 마지막에 저장된 최종 currentState를 저장하고 보여준다.

 

 

이로써 폼 빌더는 끝났다.

반응형

'[Mobile] > [Flutter]' 카테고리의 다른 글

[Flutter] Chip 사용  (0) 2023.08.28
[Flutter] 팝업 구현  (0) 2023.08.26
[Flutter] Form 빌더 동적 생성하기  (0) 2023.08.26
[Flutter] TabBar 구현 및 위젯 간 데이터 생성자  (0) 2023.08.23
[Flutter] material 앱 샘플 팁  (0) 2023.08.23