본문 바로가기

Flutter/04 Widgets

[Flutter] Widgets - FormBuilder

이번 카테고리는 form 관련 위젯인 FormBuilder 에 대해서 알아보겠습니다.

개발환경 : 윈도우11, 안드로이드 스튜디오, flutter 3.0.1

소스코드 위치 - Release 03_start&end_date · mike-bskim/flutter_form_builder_test · GitHub

 

Release 03_start&end_date · mike-bskim/flutter_form_builder_test

 

github.com

 

 

화면은 아래와 같습니다.

 

 

 

관련 패키지들

flutter_form_builder: ^7.3.1
form_builder_validators: ^8.1.1
intl: ^0.17.0

 

main.dart

 

import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:intl/intl.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Form Builder Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

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

class MyHomePageState extends State<MyHomePage> {
  final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
  final DateTime startDate = DateTime.now();
  AutovalidateMode autoValidate = AutovalidateMode.disabled;

  void _submit() {
    setState(() {
      autoValidate = AutovalidateMode.always;
    });

    final form = _fbKey.currentState;
    if (form == null || !form.validate()) {
      return;
    }

    // _fbKey.currentState!.save();
    form.save();

    // final inputValues = _fbKey.currentState!.value;
    final inputValues = form.value;
    debugPrint(inputValues.toString());
  }

// 반복되는 데코레이션을 함수로 처리
  InputDecoration inputDecoration(String label) => InputDecoration(
        filled: true,
        labelText: label,
        border: const OutlineInputBorder(),
      );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Form Builder Demo'),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.symmetric(
                vertical: 40,
                horizontal: 20,
              ),
              child: FormBuilder(
                key: _fbKey,
                autovalidateMode: autoValidate,
                child: Column(
                  children: <Widget>[
                    FormBuilderDateTimePicker(
                      // map 형식의 키값 설정, attribute >> name
                      name: 'startDate',
                      // 시간은 사용안함
                      inputType: InputType.date,
                      initialValue: startDate,
                      // 시작일 설정하면 과거 선택 불가
                      firstDate: startDate,
                      // 마지막일 범위를 지정하여 제한가능
                      lastDate: DateTime(
                          startDate.year + 1, startDate.month, startDate.day),
                      format: DateFormat('yyyy-MM-dd'),
                      decoration: inputDecoration('시작일'),
                      // 하나만 검증하려면 required 사용
                      validator: FormBuilderValidators.required(
                        errorText: '시작일은 필수입니다',
                      ),
                      // validators: [
                      //   FormBuilderValidators.required(
                      //     errorText: '시작일은 필수입니다',
                      //   )
                      // ],
                    ),
                    const SizedBox(height: 20),
                    FormBuilderDateTimePicker(
                      name: 'endDate',
                      inputType: InputType.date,
                      initialValue: startDate,
                      firstDate: startDate,
                      lastDate: DateTime(
                          startDate.year + 1, startDate.month, startDate.day),
                      format: DateFormat('yyyy-MM-dd'),
                      decoration: inputDecoration('종료일'),
                      // 여러가지 검증하려면 compose 사용
                      validator: FormBuilderValidators.compose([
                        FormBuilderValidators.required(errorText: '종료일은 필수입니다'),
                        (val) {
                          debugPrint('val: $val');
                          final sd =
                              _fbKey.currentState!.fields['startDate']!.value;
                          debugPrint('sd: $sd');

                          if (sd != null && sd.isAfter(val)) {
                            return '시작일이 종료일보다 뒤입니다';
                          }
                          return null;
                        },
                      ]),
                    ),
                  ],
                ),
              ),
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: <Widget>[
                MaterialButton(
                  onPressed: _submit,
                  color: Colors.indigo,
                  textColor: Colors.white,
                  minWidth: 120,
                  height: 45,
                  child: const Text(
                    'SUBMIT',
                    style: TextStyle(fontSize: 18),
                  ),
                ),
                MaterialButton(
                  onPressed: () {
                    _fbKey.currentState!.reset();
                  },
                  color: Colors.red,
                  textColor: Colors.white,
                  minWidth: 120,
                  height: 45,
                  child: const Text(
                    'RESET',
                    style: TextStyle(fontSize: 18),
                  ),
                ),
              ],
            )
          ],
        ),
      ),
    );
  }
}

 

 

 

 

 

[참고자료] 헤비프랜

- https://www.youtube.com/watch?v=M_0CE-IgurY&list=PLGJ958IePUyBL7BP-UU7-4AvCNw0DBy_s&index=2&t=935s