Skip to content

Commit 4a486bf

Browse files
committed
Field errorClassName/dirtyClassName/errorStyle/dirtyStyle props
1 parent 04fdf10 commit 4a486bf

File tree

2 files changed

+53
-53
lines changed

2 files changed

+53
-53
lines changed

src/Field.tsx

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,47 @@ export type FieldProps<T extends object, K extends keyof T, C> = {
4343
* You can change the behaviour of the default deserializer using the `type` prop.
4444
*/
4545
deserializer?: Deserializer<T[K]>;
46+
/**
47+
* The class to set when there is an error on this field.
48+
*/
49+
errorClassName?: string;
50+
/**
51+
* The class to set when this field has been modified.
52+
*/
53+
dirtyClassName?: string;
54+
/**
55+
* The style to set when where is an error on this field.
56+
*/
57+
errorStyle?: React.CSSProperties;
58+
/**
59+
* The style to set when this field has been modified.
60+
*/
61+
dirtyStyle?: React.CSSProperties;
4662
};
4763

4864
export function Field<T extends object, K extends keyof T, C extends React.FunctionComponent<any> | keyof JSX.IntrinsicElements = "input">(
4965
props: FieldProps<T, K, C> &
5066
Omit<ElementProps<C>, "value" | "checked" | "onChange" | "field" | keyof FieldProps<T, K, C> | keyof SerializeProps> &
5167
SerializeProps<T[K]>
5268
) {
53-
const { form, as = "input", serializer, dateAsNumber, setNullOnUncheck, setUndefinedOnUncheck, deserializer, hideWhenNull, ...rest } = props;
69+
const {
70+
form,
71+
as = "input",
72+
serializer,
73+
dateAsNumber,
74+
setNullOnUncheck,
75+
setUndefinedOnUncheck,
76+
deserializer,
77+
hideWhenNull,
78+
disabled,
79+
className,
80+
style,
81+
errorClassName,
82+
errorStyle,
83+
dirtyClassName,
84+
dirtyStyle,
85+
...rest
86+
} = props;
5487
const serializeProps = {
5588
dateAsNumber,
5689
setNullOnUncheck,
@@ -65,8 +98,9 @@ export function Field<T extends object, K extends keyof T, C extends React.Funct
6598
...rest,
6699
checked: typeof v === "boolean" ? v : undefined,
67100
value: typeof v === "boolean" ? undefined : v,
68-
disabled: field.state.isSubmitting || props.disabled,
69-
className: (field.dirty ? "field-dirty " : "") + (field.error ? "field-error " : "") + props.className,
101+
disabled: field.state.isSubmitting || disabled,
102+
className: (field.dirty ? "field-dirty " : "") + (field.error ? "field-error " : "") + (className || ""),
103+
style: { ...style, ...(field.dirty ? dirtyStyle : {}), ...(field.error ? errorStyle : {}) },
70104
field,
71105
onChange: (ev: any) => {
72106
let v = "target" in ev ? (["checkbox", "radio"].includes(props.type!) ? ev.target.checked : ev.target.value) : ev;

testing/src/Fieldform.tsx

Lines changed: 16 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,30 @@
11
import React from "react";
2-
import { useForm, Field, AnyListener, FieldError, FormField, Listener } from "typed-react-form";
2+
import { useForm, Field } from "typed-react-form";
33

4-
function Input(props: { value?: string; onChange?: (value: string) => void; style: React.CSSProperties }) {
5-
return <input style={{ padding: "0.3em", ...props.style }} value={props.value} onChange={(ev) => props.onChange?.(ev.target.value)} />;
6-
}
7-
8-
function validate(_: any) {
9-
return {
10-
email: "yikes"
11-
};
12-
}
13-
14-
function Error(props: { children: React.ReactNode; field: FormField }) {
15-
return (
16-
<p style={{ color: "red" }}>
17-
<strong>
18-
{props.children} ({props.field.dirty + ""})
19-
</strong>
20-
</p>
21-
);
4+
function CustomInput(props: { value: any; onChange: React.ChangeEventHandler; style?: React.CSSProperties; className?: string }) {
5+
return <input value={props.value} onChange={props.onChange} style={{ ...props.style, padding: "0.3em" }} className={props.className} />;
226
}
237

248
export function FieldForm() {
25-
const form = useForm({ email: "", firstName: "", gender: "male" as "male" | "female", enableEmail: true }, validate);
9+
const form = useForm({ nice: "" }, (values) => ({ nice: values.nice.length < 5 ? "Must be longer" : undefined }));
2610

2711
function submit() {
28-
console.log("this is epic");
12+
console.log(form.values);
13+
form.setDefaultValues(form.values);
2914
}
3015

3116
return (
3217
<form onSubmit={form.handleSubmit(submit)}>
33-
<Field form={form} name="firstName" as="input" />
34-
<Field form={form} name="enableEmail" type="checkbox" />
35-
<Field form={form} name="email" style={{ margin: "2em" }} />
36-
<Field form={form} name="email" as={Input} style={{ margin: "2em" }} />
37-
<FieldError form={form} name="email" as={Error} />
38-
<Field form={form} name="gender" as="select">
39-
<option value="male">male</option>
40-
<option value="female">female</option>
41-
</Field>
42-
<p>
43-
value: <Listener form={form} name="firstName" />
44-
</p>
45-
<pre>
46-
<AnyListener form={form} render={() => JSON.stringify(form.values, null, 2)} />
47-
</pre>
48-
<button type="submit">Submit</button>
49-
</form>
50-
);
51-
}
52-
53-
function CustomInput(props: { value: any; onChange: React.ChangeEventHandler; style: React.CSSProperties }) {
54-
return <input value={props.value} onChange={props.onChange} style={{ ...props.style, padding: "0.3em" }} />;
55-
}
56-
57-
function Testform() {
58-
const form = useForm({ nice: "" });
59-
return (
60-
<form>
61-
<Field form={form} name="nice" as={CustomInput} style={{ color: "gray" }} />;
18+
<Field
19+
form={form}
20+
name="nice"
21+
as={CustomInput}
22+
style={{ color: "gray", fontSize: "2em" }}
23+
className="blink"
24+
dirtyStyle={{ fontWeight: "bold" }}
25+
errorStyle={{ color: "red" }}
26+
/>
27+
<button type="submit">Go</button>
6228
</form>
6329
);
6430
}

0 commit comments

Comments
 (0)