recalculate-form v0.0.22-beta
recalculate-form
Установка
npm i recalculate-form
Or
yarn add recalculate-form
API
Form<T, M>
- основной класс для создания экземпляра формы
Типизация:
T
- значения формы;M
- типы мутаций (расширяет базовые:native
|change
)
Данные:
data
- объект с реактивными данными формы;
Методы:
getValues(): T
- метод для получения значений формы;getValues<T>(...paths: string[]): T
- метод для получения конкретных значений формы;setErrors(errors: Errors): void
- метод для установки ошибок формы;resetError(...paths: string[]): void
- метод для сброса ошибок формы(при вызове без параметров сносит все ошибки);reset(): void
- метод полной очистки формы;commit(changes: Commit<ChangeMode<M>): boolean[]
- метод для внесения изменений в поля формы;handleSubmit(onSubmit: OnSubmit<T>): (event?: FormEvent) => void
- метод для подключения html формы;
useForm<T, M>(options: FormConstructorParams<T>)
- хук для создания локального экземпляра формы;
Типизация:
T
- значения формы;M
- типы мутаций (расширяет базовые:native
|change
)
useField<T, V, M>(name: string, form?: FormConstructor<V, M>): UseFieldResult<T>
- хук для подключения html полей к форме;
Типизация:
T
- значение поля;V
- значения формы;M
- типы мутаций (расширяет базовые:native
|change
)
Возвращаемое значение:
input: object
- значения для нативного html инпута (value
,onChange
с типом мутацииnative
,name
);fieldState: object
- значение дополнительных состояний формы (isTouched
,error
);change(value: T)
- функция для мутирования значения поля (тип мутацииchange
);
useWatch<R, V, M>(paths?: string[], form?: FormConstructor<V, M>): UseFieldResult<T>
- хук подписки на отслеживание изменения полей переданных в параметре paths
;
Типизация:
V
- значения формы;R
- возвращаемое значение;M
- типы мутаций (расширяет базовые:native
|change
)
useFormState<T, M>(form?: FormConstructor<V, M>): UseFieldResult<T>
- хук подписки на отслеживание изменения состояний формы;
Типизация:
T
- значения формы;M
- типы мутаций (расширяет базовые:native
|change
);
Возвращаемое значение:
touchedFields: Record<string, boolean>
- пути к измененным значеним полей ввода;isSubmitted: boolean
- указывает на то был ли совершен вызов методаonSubmit
;isSubmitting: boolean
- состояние выполнения методаonSubmit
;
useErrors<T, M>(form?: FormConstructor<V, M>): Errors
- хук подписки на отслеживание изменения ошибок формы;
Типизация:
T
- значения формы;M
- типы мутаций (расширяет базовые:native
|change
);
Возвращаемое значение:
errors: Record<string, string | null>
- объект с ошибками формы;
useValidate<T, D, M>(validator: ValidateCallback<T, D>, deps?: D, form?: FormConstructor<V, M>): Errors
- хук для валидации формы. Вызов метода validator
производится в момент изменения значений формы;
Типизация:
T
- значения формы;D
- внешние зависимости для валидации;M
- типы мутаций (расширяет базовые:native
|change
);validator: ValidateCallback<T, D>
- метод для валидации. Принимает аргементами значения формы, ошибки и внешние зависимости;
Возвращаемые значени:
null
- сброс всех значений;{}
- нет действий (оставить все ошибки как было до вызова валидатора){ field: null }
- сбросить отдельное полеfield
useRecalculate<T, E, M>(schema: RecalculateOptions<T, E, M>, form?: FormConstructor<V, M>): JoinRecalculateResult<E>
- хук для подключения декораторов перерасчета значений;
Типизация:
T
- значения формы;E
- значения внешних значений влияющих на расчеты;M
- типы мутаций (расширяет базовые:native
|change
);
Возвращаемое значение:
callExternal(field: keyof E, value: unknown): void
- функция для вызова мутации внешних зависимостей;callRecalculate(field: string, value?: unknown): void
- функция для вызова перерасчетов формы (иммитирует изменение значения из поля ввода). Вызывает декораторы с типом мутации указанным для отслеживания;dispose: VoidFunction
- метод для очищеня дначений и отключения отслеживания значений;
useCommit<T, M>(form?: FormConstructor<T, M>): CommitFunction
- хук для получения функции мутации значений формы.
FormProvider<T, M>
- react
компонент провайдера формы;
Примеры
Бызовая форма логина
import React, { useState } from "react";
import {
useForm,
useField,
FormProvider,
useValidate,
useError,
useWatch,
} from "recalculate-form";
interface InputProps {
name: string;
type: "text" | "password";
label: string;
}
function Input({ name, type, label }: InputProps) {
const {
input,
fieldState: { error, isTouched },
} = useField<string>(name);
return (
<label>
<span>{label} </span>
<input {...input} type={type} />
{error && isTouched && <div style={{ color: "tomato" }}>{error}</div>}
</label>
);
}
function App() {
const [show, setShow] = useState(false);
const form = useForm({
defaultValues: { password: "", username: "" },
});
const { errors, resetErrors, setErrors } = useError(form);
useValidate(
({ password, username }, err, showErrors) => {
if (!showErrors) {
return null;
}
const errors: any = {};
errors.password = password.length ? null : "Error";
errors.username = username.length ? null : "Error";
return errors;
},
[show],
form
);
return (
<FormProvider form={form}>
<form onSubmit={form.handleSubmit((values) => console.log(values))}>
<h1>Login</h1>
<div>
<Input name="username" type="text" label="Username" />
</div>
<div>
<Input name="password" type="password" label="password" />
</div>
<button type="submit">Login</button>
</form>
<button onClick={() => setErrors({ loading: "random text" })}>
set errors
</button>
<button onClick={() => setErrors({ loading: null })}>
reset random errors
</button>
<button onClick={() => resetErrors()}>reset errors</button>
<button onClick={() => set(true)} disabled={c}>
on
</button>
<button onClick={() => set(false)} disabled={!c}>
off
</button>
</FormProvider>
);
}
Бызовая форма с перерасчетом значений
import { useForm, useField, useRecalculate } from "recalculate-form";
interface InputProps {
name: string;
type: "text" | "number";
label: string;
}
function Input({ name, type, label }: InputProps) {
const {
input,
fieldState: { error },
} = useField<string>(name);
return (
<label>
<span>{label} </span>
<input {...input} type={type} />
{error && <div style={{ color: "tomato" }}>{error}</div>}
</label>
);
}
function App() {
const form = useForm({
defaultValues: { first: 0, second: 0 },
});
useRecalculate(
{
fields: [
{
path: "first",
handler(current) {
return {
second: Number(current) + 10,
};
},
},
{
path: "second",
handler(current) {
return {
first: Number(current) * 10,
};
},
},
],
},
form
);
return (
<FormProvider form={form}>
<form onSubmit={form.handleSubmit((values) => console.log(values))}>
<h1>Recalculate</h1>
<div>
<Input name="first" type="number" label="First" />
</div>
<div>
<Input name="second" type="number" label="Second" />
</div>
<button type="submit">Submit</button>
</form>
</FormProvider>
);
}
Форма с перерасчетом значений и внешней зависимостью
import { useEffect, useState } from "react";
import {
useForm,
useField,
FormProvider,
useRecalculate,
} from "recalculate-form";
interface InputProps {
name: string;
type: "text" | "number";
label: string;
}
function Input({ name, type, label }: InputProps) {
const {
input,
fieldState: { error },
} = useField<string>(name);
return (
<label>
<span>{label} </span>
<input {...input} type={type} />
{error && <div style={{ color: "tomato" }}>{error}</div>}
</label>
);
}
function App() {
const [mul, setMul] = useState(10);
const form = useForm({
defaultValues: { first: 0, second: 0 },
});
const recalculate = useRecalculate(
{
defaultExternal: { multiple: mul },
fields: [
{
path: "first",
handler(current, prev, { external }) {
return {
second: Number(current) * external.multiple,
};
},
},
{
path: "second",
handler(current, prev, { external }) {
return {
first: Number(current) * external.multiple,
};
},
},
{
path: "multiple",
handler(current, prev, { lastCalledPath, values }) {
const field = lastCalledPath === "first" ? "second" : "first";
return {
[field]:
values[lastCalledPath as keyof typeof values] * Number(current),
};
},
},
],
},
form
);
useEffect(() => {
recalculate.callExternal("multiple", mul);
}, [mul]);
return (
<FormProvider form={form}>
<form onSubmit={form.handleSubmit((values) => console.log(values))}>
<h1>Recalculate external</h1>
<div>
<Input name="first" type="number" label="First" />
</div>
<div>
<Input name="second" type="number" label="Second" />
</div>
<button type="submit">Submit</button>
</form>
<button onClick={() => setMul((prev) => prev + 1)}>{mul}</button>
</FormProvider>
);
}
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
12 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago