Form#
여러 입력 필드를 묶어 유효성 검증을 수행하는 폼 컴포넌트입니다.
Live Preview#
Web
Flutter
Loading Flutter...
class FormDefaultExample extends StatelessComponent {
const FormDefaultExample({super.key});
@override
Component build(BuildContext context) {
return CoForm(
children: [
CoFormField(
label: 'Username',
child: CoTextField(
placeholder: Component.text('Username'),
onChanged: (_) {},
),
),
CoFormField(
label: 'Email',
child: CoTextField(
placeholder: Component.text('Email'),
onChanged: (_) {},
),
),
CoButton(
variant: CoreButtonVariant.primary,
onPressed: () {},
child: Component.text('Submit'),
),
],
);
}
}
class FormDefaultExample extends StatelessWidget {
const FormDefaultExample({super.key});
@override
Widget build(BuildContext context) {
return CoForm(
children: [
CoFormField(
label: 'Username',
child: CoTextField(placeholder: const Text('Username')),
),
CoFormField(
label: 'Email',
child: CoTextField(placeholder: const Text('Email')),
),
CoButton(
variant: CoreButtonVariant.primary,
onPressed: () {},
child: const Text('Submit'),
),
],
);
}
}
사용 시기 (When to Use)#
이 컴포넌트를 사용하세요:
- 여러 입력 필드의 유효성 검증을 한꺼번에 관리할 때
- 제출 전 사용자 입력을 검증하고 에러 피드백을 제공할 때
- 필드 간 상호 의존적인 검증이 필요할 때 (비밀번호 확인 등)
대신 다른 컴포넌트를 사용하세요:
Input: 단일 입력 필드만 필요하고 폼 검증이 불필요할 때Dialog: 간단한 확인 입력은 다이얼로그 내에서 직접 처리할 때
기본 사용법 (Basic Usage)#
CoForm(
children: [
CoFormField(
label: '이름',
required: true,
child: CoTextField(placeholder: Text('홍길동')),
),
CoFormField(
label: '이메일',
child: CoTextField(placeholder: Text('example@email.com')),
),
CoButton(
variant: CoreButtonVariant.primary,
onPressed: handleSubmit,
child: Text('제출'),
),
],
)
CoForm(
onSubmit: handleSubmit,
children: [
CoFormField(
label: '이름',
required: true,
child: CoTextField(placeholder: text('홍길동')),
),
CoFormField(
label: '이메일',
child: CoTextField(placeholder: text('example@email.com')),
),
CoButton(
variant: CoreButtonVariant.primary,
onPressed: handleSubmit,
child: text('제출'),
),
],
)
Props / Parameters#
CoForm#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
children |
List<Widget>? / List<Component>? |
null |
폼 내용 |
onSubmit |
VoidCallback? |
null |
폼 제출 콜백 |
gap |
double? |
CoreSpace.space24 |
필드 간 간격 |
controller |
FormController? |
null |
폼 상태 컨트롤러 (Flutter) |
CoFormField#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
label | String? | null | 필드 라벨 텍스트 |
labelWidget |
Widget? / Component? |
null |
커스텀 라벨 위젯 |
child |
Widget? / Component? |
null |
입력 위젯 |
error | String? | null | 에러 메시지 |
description |
String? |
null |
도움말 텍스트 |
required | bool | false | 필수 입력 표시 |
enabled | bool | true | 활성화 여부 |
gap |
double? |
CoreSpace.space8 |
라벨/입력/에러 간 간격 |
변형 (Variants)#
에러 상태#
CoFormField(
label: '이메일',
error: '올바른 이메일을 입력하세요',
required: true,
child: CoTextField(placeholder: Text('이메일')),
)
설명 텍스트#
CoFormField(
label: '비밀번호',
description: '8자 이상, 대소문자 및 숫자를 포함하세요',
child: CoTextField(placeholder: Text('비밀번호')),
)
비활성화#
CoFormField(
label: '이름',
enabled: false,
child: CoTextField(placeholder: Text('수정 불가')),
)
동작 스펙 (Behavior)#
유효성 검증 모드 (Flutter)#
| 모드 | 설명 |
|---|---|
initial | 필드 생성 시 즉시 검증 |
changed | 사용자가 값을 변경할 때 검증 |
submitted | 폼 제출 시 검증 |
FormController (Flutter)#
FormController로 폼 상태를 프로그래밍 방식으로 관리할 수 있습니다.
final controller = FormController();
// 값 접근
final name = controller.getValue(nameKey);
final allValues = controller.values;
// 에러 확인
final errors = controller.errors;
final nameError = controller.getSyncError(nameKey);
// 재검증
controller.revalidate(context, FormValidationMode.submitted);
Validator 시스템 (Flutter)#
검증기를 연산자로 조합할 수 있습니다.
// AND: 모든 조건 충족
final validator = NotEmptyValidator() & LengthValidator(min: 8);
// OR: 하나 이상 충족
final validator = EmailValidator() | PhoneValidator();
// NOT: 조건 반전
final validator = ~ForbiddenWordsValidator();
내장 검증기: NotEmptyValidator, LengthValidator, SafePasswordValidator,
CompareWith<T> (크로스 필드 비교), ConditionalValidator<T> (커스텀 조건)
사용 가이드라인 (Usage Guidelines)#
✅ Do#
필수 필드를 명확히 표시하세요.
CoFormField(
label: '이름',
required: true,
child: CoTextField(placeholder: Text('홍길동')),
)
어떤 필드가 필수인지 미리 알려주면 제출 실패를 줄일 수 있습니다.
❌ Don't#
필수/선택 구분 없이 필드를 나열하지 마세요.
CoFormField(
label: '이름',
// required 표시 없음
child: CoTextField(placeholder: Text('이름')),
)
사용자가 어떤 필드를 채워야 하는지 알 수 없어 제출 실패가 반복됩니다.
✅ Do#
에러 메시지에 수정 방법을 안내하세요.
CoFormField(
label: '비밀번호',
error: '8자 이상, 대소문자 및 숫자를 포함하세요',
child: CoTextField(placeholder: Text('비밀번호')),
)
구체적인 기준을 알려주면 사용자가 즉시 수정할 수 있습니다.
❌ Don't#
모호한 에러 메시지를 사용하지 마세요.
CoFormField(
label: '비밀번호',
error: '유효하지 않은 비밀번호',
child: CoTextField(placeholder: Text('비밀번호')),
)
무엇이 틀렸는지 알 수 없으면 여러 번 시도해야 합니다.
접근성 (Accessibility)#
키보드 인터랙션#
| 키 | 동작 |
|---|---|
Tab | 다음 폼 필드로 이동 |
Shift+Tab | 이전 폼 필드로 이동 |
Enter | 폼 제출 (단일 라인 입력 필드에서) |
스크린 리더#
-
Flutter:
CoFormField의label이 입력 필드와 자동 연결. 에러 발생 시 에러 메시지가 실시간으로 읽힘 - Web:
<label>요소의 네이티브 접근성 자동 처리
크로스 플랫폼 차이점 (Platform Differences)#
| 항목 | Flutter | Web |
|---|---|---|
| 클래스명 | CoForm + CoFormField |
CoForm + CoFormField |
| 상태 관리 | FormController로 중앙 관리 | HTML 폼 이벤트 기반 |
| 유효성 검증 | Validator<T> 시스템 | 기본 패턴 검증기 |
| 크로스 필드 검증 | CompareWith, shouldRevalidate | 패턴 검증기만 |
| 검증기 조합 | 연산자 (&, ` | , ~`) |
관련 컴포넌트 (Related Components)#
- Input: 텍스트 입력 필드. CoFormField로 감싸 라벨/에러 표시
- Select: 드롭다운 선택. 폼 필드로 사용 가능
- Checkbox: 체크박스 입력. 약관 동의 등에 활용
- Button: 폼 제출 버튼
조합 예제#
// 회원가입 폼 패턴
CoForm(
children: [
CoFormField(
label: '이름',
required: true,
child: CoTextField(placeholder: Text('홍길동')),
),
CoFormField(
label: '이메일',
required: true,
child: CoTextField(placeholder: Text('example@email.com')),
),
CoFormField(
label: '비밀번호',
required: true,
description: '8자 이상, 대소문자 및 숫자를 포함하세요',
child: CoTextField(placeholder: Text('비밀번호')),
),
CoButton(
variant: CoreButtonVariant.primary,
onPressed: handleSignUp,
child: Text('가입하기'),
),
],
)