Skip to content

Commit

Permalink
Feat/support custom field component, (#3858) (#3862)
Browse files Browse the repository at this point in the history
  • Loading branch information
yazaldefilimone authored Aug 11, 2023
1 parent 8255312 commit 41720c2
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 16 deletions.
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
"typescript.tsdk": "node_modules/typescript/lib",
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
}
31 changes: 17 additions & 14 deletions packages/formik/src/Field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@ export interface FieldConfig<V = any> {
* Field component to render. Can either be a string like 'select' or a component.
*/
component?:
| string
| React.ComponentType<FieldProps<V>>
| React.ComponentType
| React.ForwardRefExoticComponent<any>;
| string
| React.ComponentType<FieldProps<V>>
| React.ComponentType
| React.ForwardRefExoticComponent<any>;

/**
* Component to render. Can either be a string e.g. 'select', 'input', or 'textarea', or a component.
*/
as?:
| React.ComponentType<FieldProps<V>['field']>
| string
| React.ComponentType
| React.ForwardRefExoticComponent<any>;
| React.ComponentType<FieldProps<V>['field']>
| string
| React.ComponentType
| React.ForwardRefExoticComponent<any>;

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

export type FieldAttributes<T> = GenericFieldHTMLAttributes &
export type FieldAttributes<T> = { className?: string; } & GenericFieldHTMLAttributes &
FieldConfig<T> &
T & { name: string };
T & {
name: string,
};

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

Expand Down Expand Up @@ -139,6 +141,7 @@ export function Field({
children,
as: is, // `as` is reserved in typescript lol
component,
className,
...props
}: FieldAttributes<any>) {
const {
Expand Down Expand Up @@ -202,14 +205,14 @@ export function Field({
const { innerRef, ...rest } = props;
return React.createElement(
component,
{ ref: innerRef, ...field, ...rest },
{ ref: innerRef, ...field, ...rest, className },
children
);
}
// We don't pass `meta` for backwards compat
return React.createElement(
component,
{ field, form: formik, ...props },
{ field, form: formik, ...props, className },
children
);
}
Expand All @@ -221,10 +224,10 @@ export function Field({
const { innerRef, ...rest } = props;
return React.createElement(
asElement,
{ ref: innerRef, ...field, ...rest },
{ ref: innerRef, ...field, ...rest, className },
children
);
}

return React.createElement(asElement, { ...field, ...props }, children);
return React.createElement(asElement, { ...field, ...props, className }, children);
}
20 changes: 19 additions & 1 deletion packages/formik/test/Field.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,10 @@ describe('Field / FastField', () => {

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

it('<FastField />', () => {
Expand All @@ -110,6 +112,22 @@ describe('Field / FastField', () => {
});
});

describe('renders an <input /> with className', () => {
it('<Field />', () => {
const className = 'field-custom'
const { container } = renderForm(<Field name="name" className={className} />);
expect(container.querySelectorAll(`.${className}`)).toHaveLength(1)
expect(container.querySelector(`.${className}`)?.getAttribute('value')).toEqual('jared')
});

it('<FastField />', () => {
const className = 'field-custom'
const { container } = renderForm(<FastField name="name" className={className} />);
expect(container.querySelectorAll(`.${className}`)).toHaveLength(1)
expect(container.querySelector(`.${className}`)?.getAttribute('value')).toEqual('jared')
});
});

describe('receives { field, form, meta } props and renders element', () => {
it('<Field />', () => {
let injected: FieldProps[] = [];
Expand Down

1 comment on commit 41720c2

@vercel
Copy link

@vercel vercel bot commented on 41720c2 Aug 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

formik-docs – ./website

formik-docs-formik.vercel.app
formik-docs.vercel.app
www.formik.org
formik-docs-git-main-formik.vercel.app
formik.org

Please sign in to comment.