Skip to content

Commit 41720c2

Browse files
Feat/support custom field component, (#3858) (#3862)
1 parent 8255312 commit 41720c2

File tree

3 files changed

+41
-16
lines changed

3 files changed

+41
-16
lines changed

.vscode/settings.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
{
2-
"typescript.tsdk": "node_modules/typescript/lib"
2+
"typescript.tsdk": "node_modules/typescript/lib",
3+
"editor.formatOnSave": false,
4+
"editor.codeActionsOnSave": {
5+
"source.fixAll.eslint": true
6+
},
37
}

packages/formik/src/Field.tsx

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,19 @@ export interface FieldConfig<V = any> {
2222
* Field component to render. Can either be a string like 'select' or a component.
2323
*/
2424
component?:
25-
| string
26-
| React.ComponentType<FieldProps<V>>
27-
| React.ComponentType
28-
| React.ForwardRefExoticComponent<any>;
25+
| string
26+
| React.ComponentType<FieldProps<V>>
27+
| React.ComponentType
28+
| React.ForwardRefExoticComponent<any>;
2929

3030
/**
3131
* Component to render. Can either be a string e.g. 'select', 'input', or 'textarea', or a component.
3232
*/
3333
as?:
34-
| React.ComponentType<FieldProps<V>['field']>
35-
| string
36-
| React.ComponentType
37-
| React.ForwardRefExoticComponent<any>;
34+
| React.ComponentType<FieldProps<V>['field']>
35+
| string
36+
| React.ComponentType
37+
| React.ForwardRefExoticComponent<any>;
3838

3939
/**
4040
* Render prop (works like React router's <Route render={props =>} />)
@@ -72,9 +72,11 @@ export interface FieldConfig<V = any> {
7272
innerRef?: (instance: any) => void;
7373
}
7474

75-
export type FieldAttributes<T> = GenericFieldHTMLAttributes &
75+
export type FieldAttributes<T> = { className?: string; } & GenericFieldHTMLAttributes &
7676
FieldConfig<T> &
77-
T & { name: string };
77+
T & {
78+
name: string,
79+
};
7880

7981
export type FieldHookConfig<T> = GenericFieldHTMLAttributes & FieldConfig<T>;
8082

@@ -139,6 +141,7 @@ export function Field({
139141
children,
140142
as: is, // `as` is reserved in typescript lol
141143
component,
144+
className,
142145
...props
143146
}: FieldAttributes<any>) {
144147
const {
@@ -202,14 +205,14 @@ export function Field({
202205
const { innerRef, ...rest } = props;
203206
return React.createElement(
204207
component,
205-
{ ref: innerRef, ...field, ...rest },
208+
{ ref: innerRef, ...field, ...rest, className },
206209
children
207210
);
208211
}
209212
// We don't pass `meta` for backwards compat
210213
return React.createElement(
211214
component,
212-
{ field, form: formik, ...props },
215+
{ field, form: formik, ...props, className },
213216
children
214217
);
215218
}
@@ -221,10 +224,10 @@ export function Field({
221224
const { innerRef, ...rest } = props;
222225
return React.createElement(
223226
asElement,
224-
{ ref: innerRef, ...field, ...rest },
227+
{ ref: innerRef, ...field, ...rest, className },
225228
children
226229
);
227230
}
228231

229-
return React.createElement(asElement, { ...field, ...props }, children);
232+
return React.createElement(asElement, { ...field, ...props, className }, children);
230233
}

packages/formik/test/Field.test.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,10 @@ describe('Field / FastField', () => {
100100

101101
describe('renders an <input /> by default', () => {
102102
it('<Field />', () => {
103-
const { container } = renderForm(<Field name="name" />);
103+
const className = 'field-custom'
104+
const { container } = renderForm(<Field name="name" className={className} />);
104105
expect(container.querySelectorAll('input')).toHaveLength(1);
106+
expect(container.querySelector(`.${className}`)?.getAttribute('value')).toEqual('jared')
105107
});
106108

107109
it('<FastField />', () => {
@@ -110,6 +112,22 @@ describe('Field / FastField', () => {
110112
});
111113
});
112114

115+
describe('renders an <input /> with className', () => {
116+
it('<Field />', () => {
117+
const className = 'field-custom'
118+
const { container } = renderForm(<Field name="name" className={className} />);
119+
expect(container.querySelectorAll(`.${className}`)).toHaveLength(1)
120+
expect(container.querySelector(`.${className}`)?.getAttribute('value')).toEqual('jared')
121+
});
122+
123+
it('<FastField />', () => {
124+
const className = 'field-custom'
125+
const { container } = renderForm(<FastField name="name" className={className} />);
126+
expect(container.querySelectorAll(`.${className}`)).toHaveLength(1)
127+
expect(container.querySelector(`.${className}`)?.getAttribute('value')).toEqual('jared')
128+
});
129+
});
130+
113131
describe('receives { field, form, meta } props and renders element', () => {
114132
it('<Field />', () => {
115133
let injected: FieldProps[] = [];

0 commit comments

Comments
 (0)