Form validators
Form validators (폼 검증자)
@mantine/form이 제공하는 미리 만들어진 검증 함수들(isNotEmpty, isEmail, matches, hasLength 등)을 다뤄요. 각 검증자는 작고 기본적인 검증을 제공하며, 복잡한 검증이 필요하면 다른 검증 방식을 사용해요. 검증자 하나씩 설명해 드릴게요.
출처: 문서
본문
사용법
@mantine/form 패키지는 검증 규칙 객체에서 사용할 수 있는 여러 함수를 내보내요. 검증 함수는 크기가 아주 작고 기본 검증을 제공해요. 복잡한 검증 요구사항이 있다면 다른 유형의 검증을 사용하세요.
import { useForm, isNotEmpty, isEmail, isInRange, hasLength, matches, isUrl, isOneOf } from '@mantine/form';
import { Button, Group, TextInput, NumberInput, NativeSelect } from '@mantine/core';
function Demo() {
const form = useForm({
mode: 'uncontrolled',
initialValues: {
name: '',
job: '',
email: '',
favoriteColor: '',
age: 18,
website: '',
role: '',
},
validate: {
name: hasLength({ min: 2, max: 10 }, 'Name must be 2-10 characters long'),
job: isNotEmpty('Enter your current job'),
email: isEmail('Invalid email'),
favoriteColor: matches(/^#([0-9a-f]{3}){1,2}$/, 'Enter a valid hex color'),
age: isInRange({ min: 18, max: 99 }, 'You must be 18-99 years old to register'),
website: isUrl('Invalid URL'),
role: isOneOf(['developer', 'designer', 'manager'], 'Pick a valid role'),
},
});
return (
<form onSubmit={form.onSubmit(() => {})}>
<TextInput
label="Name"
placeholder="Name"
withAsterisk
key={form.key('name')}
{...form.getInputProps('name')}
/>
<TextInput
label="Your job"
placeholder="Your job"
withAsterisk
mt="md"
key={form.key('job')}
{...form.getInputProps('job')}
/>
<TextInput
label="Your email"
placeholder="Your email"
withAsterisk
mt="md"
key={form.key('email')}
{...form.getInputProps('email')}
/>
<TextInput
label="Your favorite color"
placeholder="Your favorite color"
withAsterisk
mt="md"
key={form.key('favoriteColor')}
{...form.getInputProps('favoriteColor')}
/>
<NumberInput
label="Your age"
placeholder="Your age"
withAsterisk
mt="md"
key={form.key('age')}
{...form.getInputProps('age')}
/>
<TextInput
label="Your website"
placeholder="https://example.com"
withAsterisk
mt="md"
key={form.key('website')}
{...form.getInputProps('website')}
/>
<NativeSelect
label="Your role"
data={['', 'developer', 'designer', 'manager']}
withAsterisk
mt="md"
key={form.key('role')}
{...form.getInputProps('role')}
/>
<Group justify="flex-end" mt="md">
<Button type="submit">Submit</Button>
</Group>
</form>
);
}
선택적 오류 (Optional error)
아래 모든 검증 함수의 마지막 인자는 선택이에요. 오류를 설정하지 않으면 검증에 실패한 필드는 오류 메시지 없이 유효하지 않은 스타일만 가져요:
import { useForm, isNotEmpty, isEmail, isInRange, hasLength, matches, isUrl, isOneOf } from '@mantine/form';
import { Button, Group, TextInput, NumberInput, NativeSelect } from '@mantine/core';
function Demo() {
const form = useForm({
mode: 'uncontrolled',
initialValues: {
name: '',
job: '',
email: '',
favoriteColor: '',
age: 18,
website: '',
role: '',
},
validate: {
name: hasLength({ min: 2, max: 10 }),
job: isNotEmpty(),
email: isEmail(),
favoriteColor: matches(/^#([0-9a-f]{3}){1,2}$/),
age: isInRange({ min: 18, max: 99 }),
website: isUrl(),
role: isOneOf(['developer', 'designer', 'manager']),
},
});
return (
<form onSubmit={form.onSubmit(() => {})}>
<TextInput
label="Name"
placeholder="Name"
withAsterisk
key={form.key('name')}
{...form.getInputProps('name')}
/>
<TextInput
label="Your job"
placeholder="Your job"
withAsterisk
mt="md"
key={form.key('job')}
{...form.getInputProps('job')}
/>
<TextInput
label="Your email"
placeholder="Your email"
withAsterisk
mt="md"
key={form.key('email')}
{...form.getInputProps('email')}
/>
<TextInput
label="Your favorite color"
placeholder="Your favorite color"
withAsterisk
mt="md"
key={form.key('favoriteColor')}
{...form.getInputProps('favoriteColor')}
/>
<NumberInput
label="Your age"
placeholder="Your age"
withAsterisk
mt="md"
key={form.key('age')}
{...form.getInputProps('age')}
/>
<TextInput
label="Your website"
placeholder="https://example.com"
withAsterisk
mt="md"
key={form.key('website')}
{...form.getInputProps('website')}
/>
<NativeSelect
label="Your role"
data={['', 'developer', 'designer', 'manager']}
withAsterisk
mt="md"
key={form.key('role')}
{...form.getInputProps('role')}
/>
<Group justify="flex-end" mt="md">
<Button type="submit">Submit</Button>
</Group>
</form>
);
}
isNotEmpty
isNotEmpty는 폼 값이 비어있지 않은지 확인해요. 빈 문자열, 빈 배열, false, null, undefined 값은 비어있는 것으로 간주돼요. 문자열은 검증 전에 trim돼요:
import { isNotEmpty, useForm } from '@mantine/form';
const form = useForm({
mode: 'uncontrolled',
initialValues: {
name: '',
acceptTermsOfUse: false,
country: null,
previousJobs: [],
},
validate: {
// Empty strings are considered to be invalid
name: isNotEmpty('Name cannot be empty'),
// False value is considered to be invalid
acceptTermsOfUse: isNotEmpty('You must accept terms of use'),
// null is considered to be invalid
country: isNotEmpty('Pick your country'),
// Empty arrays are considered to be invalid
previousJobs: isNotEmpty('Enter at least one job'),
},
});
isEmail
isEmail은 /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,})+$/ 정규식으로 폼 값이 이메일인지 판단해요:
import { isEmail, useForm } from '@mantine/form';
const form = useForm({
mode: 'uncontrolled',
initialValues: {
email: '',
},
validate: {
email: isEmail('Invalid email'),
},
});
matches
matches는 폼 값이 주어진 정규식과 일치하는지 확인해요. 폼 값이 문자열이 아니면 검증이 실패해요:
import { matches, useForm } from '@mantine/form';
const form = useForm({
mode: 'uncontrolled',
initialValues: {
color: '',
},
validate: {
color: matches(/^#([0-9a-f]{3}){1,2}$/, 'Invalid color'),
},
});
isInRange
isInRange는 폼 값이 주어진 min-max 범위 안에 있는지 확인해요. 폼 값이 숫자가 아니면 검증이 실패해요:
import { isInRange, useForm } from '@mantine/form';
const form = useForm({
mode: 'uncontrolled',
initialValues: {
maxRange: 0,
minRange: 0,
minMaxRange: 0,
},
validate: {
maxRange: isInRange({ max: 20 }, 'Value must be 20 or less'),
minRange: isInRange({ min: 10 }, 'Value must be 10 or more'),
minMaxRange: isInRange(
{ min: 10, max: 20 },
'Value must be between 10 and 20'
),
},
});
hasLength
hasLength는 폼 값의 길이가 주어진 min-max 범위 안에 있는지 확인해요. hasLength는 문자열, 배열, 그리고 length 속성을 가진 다른 어떤 객체와도 올바르게 동작해요. 문자열은 검증 전에 trim돼요:
import { hasLength, useForm } from '@mantine/form';
const form = useForm({
mode: 'uncontrolled',
initialValues: {
exact: '',
maxLength: '',
minLength: '',
minMaxLength: '',
},
validate: {
exact: hasLength(5, 'Values must have exactly 5 characters'),
maxLength: hasLength(
{ max: 20 },
'Value must have 20 or less characters'
),
minLength: hasLength(
{ min: 10 },
'Value must have 10 or more characters'
),
minMaxLength: hasLength(
{ min: 10, max: 20 },
'Value must have 10-20 characters'
),
},
});
matchesField
matchesField는 폼 값이 다른 폼 필드의 값과 같은지 확인해요. matchesField는 원시 값(primitive)에서만 동작한다는 점에 주의하세요(배열과 객체는 비교할 수 없어요):
import { matchesField, useForm } from '@mantine/form';
const form = useForm({
mode: 'uncontrolled',
initialValues: {
password: '',
confirmPassword: '',
},
validate: {
confirmPassword: matchesField(
'password',
'Passwords are not the same'
),
},
});
isJSONString
isJSONString은 폼 값이 유효한 JSON 문자열인지 확인해요:
import { isJSONString, useForm } from '@mantine/form';
const form = useForm({
mode: 'uncontrolled',
initialValues: {
json: '',
},
validate: {
json: isJSONString('Invalid JSON string'),
},
});
isUrl
isUrl는 폼 값이 유효한 URL인지 확인해요. 기본적으로 http와 https 프로토콜만 허용되고 localhost는 거부돼요. 첫 번째 인자로 옵션을 전달해 이 동작을 커스터마이즈할 수 있어요:
import { isUrl, useForm } from '@mantine/form';
const form = useForm({
mode: 'uncontrolled',
initialValues: {
website: '',
internalUrl: '',
ftpServer: '',
},
validate: {
// Basic URL validation
website: isUrl('Invalid URL'),
// Allow localhost URLs
internalUrl: isUrl(
{ allowLocalhost: true },
'Invalid URL'
),
// Allow custom protocols
ftpServer: isUrl(
{ protocols: ['ftp', 'https'] },
'Invalid FTP or HTTPS URL'
),
},
});
isOneOf
isOneOf는 폼 값이 주어진 허용 값 목록에 포함되는지 확인해요. 비교는 엄격한 동등(strict equality)을 사용해요:
import { isOneOf, useForm } from '@mantine/form';
const form = useForm({
mode: 'uncontrolled',
initialValues: {
role: '',
priority: 0,
},
validate: {
role: isOneOf(
['admin', 'user', 'moderator'],
'Invalid role'
),
priority: isOneOf([1, 2, 3], 'Priority must be 1, 2, or 3'),
},
});
isNotEmptyHTML
isNotEmptyHTML은 폼 값이 빈 HTML 문자열이 아닌지 확인해요. 빈 문자열, HTML 태그와 공백만 있는 문자열은 비어있는 것으로 간주돼요:
import { isNotEmptyHTML, useForm } from '@mantine/form';
const form = useForm({
mode: 'uncontrolled',
initialValues: {
html: '',
},
validate: {
html: isNotEmptyHTML('HTML cannot be empty'),
},
});
더 알아보기 (Learn more)
- Form schema validation — 폼 스키마 검증
- Nested fields — 중첩 필드