/
sdds
/
plasma
Обзор
Документация
Войти
/
sdds
/
plasma
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
dev
website/sdds-dfa-docs/docs/form/NativeForm.mdx
565 строк
21 KB
Ilya
feat(*): update docs for form select
17 дек 2024, 02:04
17 дек 2024, 02:04
43b194e
Код
Авторство
О чём код?
--- id: native-form title: Нативная форма sidebar_position: 3 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Нативная форма Для работы с простой формой ( имеется ввиду html тег `<form>` ) можно использовать следующий подход. ```tsx live import React from 'react'; import { Button, TextField, TextArea, Checkbox, Switch, Radiobox, RadioGroup, Slider, DatePicker, Autocomplite } from "@salutejssdds-dfa"; export function App() { const langName = 'language'; const radioboxItems = [ { langName, value: 'c', label: 'C', disabled: false }, { langName, value: 'cpp', label: 'C++', disabled: false }, { langName, value: 'assembly', label: 'Assembly', disabled: false }, ]; const onSubmit = (event) => { event.preventDefault(); const formData = new FormData(event.target); for (const [name, value] of formData) { console.log(name, value); } }; const mockData = [ { label: 'Алексей Смирнов' }, { label: 'Екатерина Иванова' }, { label: 'Дмитрий Петров' }, { label: 'Ольга Васильева' }, { label: 'Сергей Сидоров' }, { label: 'Мария Кузнецова' }, { label: 'Андрей Попов' }, { label: 'Анна Николаева' }, { label: 'Иван Федоров' }, { label: 'Наталья Морозова' }, { label: 'Михаил Павлов' }, { label: 'Елена Романова' }, { label: 'Владимир Киселев' }, { label: 'Татьяна Захарова' }, { label: 'Николай Семенов' }, { label: 'Юлия Белова' }, { label: 'Александр Гусев' }, { label: 'Оксана Яковлева' }, { label: 'Игорь Егорова' }, { label: 'Вера Тихомирова' }, { label: 'Артем Григорьев' }, { label: 'Евгения Козлова' }, { label: 'Максим Лебедев' }, { label: 'Виктория Калашникова' }, { label: 'Константин Абрамов' }, { label: 'Светлана Новикова' }, { label: 'Юрий Волков' }, { label: 'Валентина Воробьева' }, { label: 'Павел Сергеев' }, { label: 'Людмила Виноградова' }, { label: 'Антон Соловьев' }, { label: 'Маргарита Цветкова' }, { label: 'Роман Трофимов' }, { label: 'Лариса Зайцева' }, { label: 'Евгений Никитин' }, { label: 'Галина Михайлова' }, { label: 'Владислав Антонов' }, { label: 'Дарья Филатова' }, { label: 'Олег Буров' }, { label: 'Инна Медведева' }, { label: 'Вячеслав Крылов' }, { label: 'Тамара Беляева' }, { label: 'Кирилл Марков' }, { label: 'Марина Пономарева' }, { label: 'Борис Захаров' }, { label: 'Жанна Савельева' }, { label: 'Федор Жуков' }, { label: 'Елизавета Логинова' }, { label: 'Виктор Рыбаков' }, { label: 'Лилия Макарова' }, ]; const items = [ { value: 'north_america', label: 'Северная Америка', }, { value: 'south_america', label: 'Южная Америка', items: [ { value: 'brazil', label: 'Бразилия', items: [ { value: 'rio_de_janeiro', label: 'Рио-де-Жанейро', }, { value: 'sao_paulo', label: 'Сан-Паулу', }, ], }, { value: 'argentina', label: 'Аргентина', items: [ { value: 'buenos_aires', label: 'Буэнос-Айрес', }, { value: 'cordoba', label: 'Кордова', }, ], }, { value: 'colombia', label: 'Колумбия', items: [ { value: 'bogota', label: 'Богота', }, { value: 'medellin', label: 'Медельин', }, ], }, ], }, { value: 'europe', label: 'Европа', items: [ { value: 'france', label: 'Франция', items: [ { value: 'paris', label: 'Париж', }, { value: 'lyon', label: 'Лион', }, ], }, { value: 'germany', label: 'Германия', items: [ { value: 'berlin', label: 'Берлин', }, { value: 'munich', label: 'Мюнхен', }, ], }, { value: 'italy', label: 'Италия', items: [ { value: 'rome', label: 'Рим', }, { value: 'milan', label: 'Милан', }, ], }, { value: 'spain', label: 'Испания', items: [ { value: 'madrid', label: 'Мадрид', }, { value: 'barcelona', label: 'Барселона', }, ], }, { value: 'united_kingdom', label: 'Великобритания', items: [ { value: 'london', label: 'Лондон', }, { value: 'manchester', label: 'Манчестер', }, ], }, ], }, { value: 'asia', label: 'Азия', items: [ { value: 'china', label: 'Китай', items: [ { value: 'beijing', label: 'Пекин', }, { value: 'shanghai', label: 'Шанхай', }, ], }, { value: 'japan', label: 'Япония', items: [ { value: 'tokyo', label: 'Токио', }, { value: 'osaka', label: 'Осака', }, ], }, { value: 'india', label: 'Индия', items: [ { value: 'delhi', label: 'Дели', }, { value: 'mumbai', label: 'Мумбаи', }, ], }, { value: 'south_korea', label: 'Южная Корея', items: [ { value: 'seoul', label: 'Сеул', }, { value: 'busan', label: 'Пусан', }, ], }, { value: 'thailand', label: 'Таиланд', items: [ { value: 'bangkok', label: 'Бангкок', }, { value: 'phuket', label: 'Пхукет', }, ], }, ], }, { value: 'africa', label: 'Африка', isDisabled: true, }, ]; return ( <form onSubmit={onSubmit} style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}> <TextField name="textfield" placeholder="Textfield" /> <TextArea name="textarea" autoResize placeholder="Textarea" /> <Checkbox name="checkbox" label="Checkbox" /> <Switch name="switch" label="Switch" labelPosition="after" /> <RadioGroup aria-labelledby="radiogroup-title-id"> <div id="radiogroup-title-id" style={{ margin: '1rem 0', fontWeight: '600' }}> Выберите язык программирования для изучения. </div> {radioboxItems.map((item) => ( <Radiobox name="radiobox" key={item.value} value={item.value} label={item.label} disabled={item.disabled} /> ))} </RadioGroup> <Slider name="slider" label="Slider" type="single" min={0} max={100} /> <DatePicker label="DatePicker" name="datepicker" /> <Autocomplete suggestions={mockData} listMaxHeight="250px" label="Label" placeholder="Placeholder" leftHelper="Введите имя Алексей" /> <Combobox label="Combobox" name="combobox" items={items} /> <Select label="Combobox" name="combobox" items={items} /> <Button type="submit">Отправить</Button> </form> ); } ``` ## Валидация Для валидации можно использовать как сторонние библиотеки, так и собственное решение: <Tabs> <TabItem value="custom" label="Собственное решение" default> [Пример CodeSandbox](https://codesandbox.io/p/sandbox/sdds-custom-form-validation-pdg9y7) ```tsx export function App() { const emailOptions = { minLength: { value: 7, errorMessage: 'Почта слишком короткая', }, maxLength: { value: 30, errorMessage: 'Почта слишком длинная', }, minHostLength: { value: 2, errorMessage: 'Хост слишком короткий', }, maxHostLength: { value: 12, errorMessage: 'Хост слишком длинный', }, minDomainLength: { value: 3, errorMessage: 'Домен слишком короткий', }, maxDomainLength: { value: 6, errorMessage: 'Домен слишком длинный', }, minZoneLength: { value: 2, errorMessage: 'Доменная зона слишком короткая', }, maxZoneLength: { value: 5, errorMessage: 'Доменная зона слишком длинная', }, whitelistDomains: { value: ['plasma.ru', 'gmail.com', 'mail.ru'], errorMessage: 'Домен не разрешен', }, blacklistDomains: { value: ['hah.ah', 'heh.eh'], errorMessage: 'Домен запрещен', }, }; const passwordOptions = { minLength: { value: 5, errorMessage: 'Пароль слишком короткий', }, maxLength: { value: 20, errorMessage: 'Пароль слишком длинный', }, includeUppercase: { value: true, errorMessage: 'Пароль должен содержать хотя бы одну заглавную букву', }, includeLowercase: { value: true, errorMessage: 'Пароль должен содержать хотя бы одну строчную букву', }, includeDigits: { value: true, errorMessage: 'Пароль должен содержать хотя бы одну цифру', }, includeSpecialSymbols: { value: true, errorMessage: 'Пароль должен содержать хотя бы один специальный символ', }, }; const [emailError, setEmailError] = useState(''); const [passwordError, setPasswordError] = useState(''); const [hidden, setHidden] = useState(false); const handleOnChange = () => { setEmailError(''); }; const handleOnValidate = ({ errorMessage }: { errorMessage?: string }) => { setPasswordError(errorMessage || ''); }; const toggleShowPassword = () => setHidden(!hidden); const HideButton = () => ( <IconButton size="s" view="clear" onClick={toggleShowPassword}> {hidden ? <IconEyeClosedFill size="xs" color="inherit" /> : <IconEyeFill size="xs" color="inherit" />} </IconButton> ); const { handleValidationBlur: handleBlurEmail, handleValidationKeyDown: handleKeyDownEmail } = useValidation({ validationType: 'email', options: emailOptions, onValidate: handleOnValidate, }); const { handleValidationBlur: handleBlurPassword, handleValidationKeyDown: handleKeyDownPassword } = useValidation({ validationType: 'password', options: passwordOptions, onValidate: handleOnValidate, }); return ( <div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}> <TextField label="Валидация почты" placeholder="Заполните поле" view={emailError ? "negative" : "default"} leftHelper={emailError || "Валидация почты"} onChange={handleOnChange} onBlur={handleBlurEmail} onKeyDown={handleKeyDownEmail} /> <TextField label="Валидация пароля" placeholder="Заполните поле" view={passwordError ? "negative" : "default"} leftHelper={passwordError || "Валидация пароля"} type={hidden ? "password" : "text"} onChange={handleOnChange} onBlur={handleBlurPassword} onKeyDown={handleKeyDownPassword} passwordHidden={hidden} contentRight={<HideButton />} /> </div> ); } ``` </TabItem> <TabItem value="yup" label="Валидация с yup" default> [Пример CodeSandbox](https://codesandbox.io/p/sandbox/sdds-native-form-validation-59vhzv) ```tsx export function App() { const schema = yup .object({ email: yup .string() .email("Некорректная почта") .required("Заполните поле"), tel: yup .string() .required("Заполните поле") .min(22, "Телефон должен содержать 11 цифр"), password: yup .string() .required("Заполните поле") .min(8, "Пароль должен быть не менее 8 символов"), }) .required(); const [errors, setErrors] = useState({}); const onSubmit = async (event) => { event.preventDefault(); const formData = new FormData(event.target); const data = Object.fromEntries(formData.entries()); try { const validatedData = await schema.validate(data, { abortEarly: false, }); console.log(validatedData); } catch (err) { const errors = err.inner.reduce((acc, error) => { return { ...acc, [error.path]: error.message, }; }, {}); setErrors(errors); } }; const handleChange = (event, name) => { console.log(name); setErrors((prevErrors) => ({ ...prevErrors, [name]: "" })); }; console.log(errors); return ( <form onSubmit={onSubmit} style={{ display: "flex", flexDirection: "column", gap: "20px" }} > <TextField name="email" placeholder="Почта" view={errors?.email ? "negative" : "default"} leftHelper={errors?.email} onChange={(e) => handleChange(e, "email")} required={false} /> <Mask name="tel" placeholder="Телефон" mask="+7 (000) 000 - 00 - 00" maskChar="_" view={errors?.tel ? "negative" : "default"} leftHelper={errors?.tel} onChange={(e) => handleChange(e, "tel")} required={false} /> <TextField name="password" type="password" placeholder="Пароль" view={errors?.password ? "negative" : "default"} leftHelper={errors?.password} onChange={(e) => handleChange(e, "password")} required={false} /> <Button type="submit">Войти</Button> </form> ); } ``` </TabItem> </Tabs>