mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Add FieldArray component (#26993)
This commit is contained in:
parent
58627a0c38
commit
c730e659e3
40
packages/grafana-ui/src/components/Forms/FieldArray.mdx
Normal file
40
packages/grafana-ui/src/components/Forms/FieldArray.mdx
Normal file
@ -0,0 +1,40 @@
|
||||
import { Meta, Props } from '@storybook/addon-docs/blocks';
|
||||
import { FieldArray } from './FieldArray';
|
||||
|
||||
<Meta title="MDX|FieldArray" component={FieldArray} />
|
||||
|
||||
# FieldArray
|
||||
|
||||
`FieldArray` provides a way to render a list of dynamic inputs. It exposes the functionality of `useFieldArray` in [react-hook-form](https://react-hook-form.com/advanced-usage/#FieldArrays). `FieldArray` must be wrapped at some level by a `<Form>` element.
|
||||
|
||||
### Usage
|
||||
|
||||
```jsx
|
||||
import { Form, FieldArray } from '@grafana/ui';
|
||||
|
||||
<Form>
|
||||
({control, register}) => (
|
||||
<FieldArray control={control} name="People">
|
||||
{({ fields, append }) => (
|
||||
<div>
|
||||
{fields.map((field, index) => (
|
||||
<div key={field.id}>
|
||||
<Input key={index} ref={register()} name=`people[${index}].firstName` value={field.firstName} />
|
||||
<Input ref={register()} name=`people[${index}].lastName` value={field.lastName} />
|
||||
</div>
|
||||
))}
|
||||
<Button onClick={() => append({firstName: 'Roger', lastName: 'Waters'})}>Append</Button>
|
||||
</div>
|
||||
)}
|
||||
</FieldArray>
|
||||
)
|
||||
</Form>;
|
||||
```
|
||||
|
||||
### FieldArray API
|
||||
|
||||
The `FieldArray` component exposes its API via render prop. Properties exposed are: `fields`, `append`, `prepend`, `remove`, `swap`, `move`, `insert`
|
||||
|
||||
### Props
|
||||
|
||||
<Props of={FieldArray} />
|
@ -0,0 +1,52 @@
|
||||
import React from 'react';
|
||||
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||
import { withStoryContainer } from '../../utils/storybook/withStoryContainer';
|
||||
import { Form, Input, Button, HorizontalGroup } from '@grafana/ui';
|
||||
import { FieldArray } from './FieldArray';
|
||||
import mdx from './FieldArray.mdx';
|
||||
|
||||
export default {
|
||||
title: 'Forms/FieldArray',
|
||||
component: FieldArray,
|
||||
decorators: [withStoryContainer, withCenteredStory],
|
||||
parameters: {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const simple = () => {
|
||||
const defaultValues = {
|
||||
people: [{ firstName: 'Janis', lastName: 'Joplin' }],
|
||||
};
|
||||
return (
|
||||
<Form onSubmit={values => console.log(values)} defaultValues={defaultValues}>
|
||||
{({ control, register }) => (
|
||||
<div>
|
||||
<FieldArray control={control} name="people">
|
||||
{({ fields, append }) => (
|
||||
<>
|
||||
<div style={{ marginBottom: '1rem' }}>
|
||||
{fields.map((field, index) => (
|
||||
<HorizontalGroup key={field.id}>
|
||||
<Input ref={register()} name={`people[${index}].firstName`} value={field.firstName} />
|
||||
<Input ref={register()} name={`people[${index}].lastName`} value={field.lastName} />
|
||||
</HorizontalGroup>
|
||||
))}
|
||||
</div>
|
||||
<Button
|
||||
style={{ marginRight: '1rem' }}
|
||||
onClick={() => append({ firstName: 'Roger', lastName: 'Waters' })}
|
||||
>
|
||||
Add another
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</FieldArray>
|
||||
<Button type="submit">Submit</Button>
|
||||
</div>
|
||||
)}
|
||||
</Form>
|
||||
);
|
||||
};
|
15
packages/grafana-ui/src/components/Forms/FieldArray.tsx
Normal file
15
packages/grafana-ui/src/components/Forms/FieldArray.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import { FC } from 'react';
|
||||
import { useFieldArray, UseFieldArrayProps } from 'react-hook-form';
|
||||
import { FieldArrayApi } from '../../types';
|
||||
|
||||
export interface FieldArrayProps extends UseFieldArrayProps {
|
||||
children: (api: FieldArrayApi) => JSX.Element;
|
||||
}
|
||||
|
||||
export const FieldArray: FC<FieldArrayProps> = ({ name, control, children }) => {
|
||||
const { fields, append, prepend, remove, swap, move, insert } = useFieldArray({
|
||||
control,
|
||||
name,
|
||||
});
|
||||
return children({ fields, append, prepend, remove, swap, move, insert });
|
||||
};
|
@ -1,7 +1,19 @@
|
||||
import { FormContextValues } from 'react-hook-form';
|
||||
import { FormContextValues, FieldValues, ArrayField } from 'react-hook-form';
|
||||
export { OnSubmit as FormsOnSubmit, FieldErrors as FormFieldErrors } from 'react-hook-form';
|
||||
|
||||
export type FormAPI<T> = Pick<
|
||||
FormContextValues<T>,
|
||||
'register' | 'errors' | 'control' | 'formState' | 'getValues' | 'watch'
|
||||
>;
|
||||
|
||||
type FieldArrayValue = Partial<FieldValues> | Array<Partial<FieldValues>>;
|
||||
|
||||
export interface FieldArrayApi {
|
||||
fields: Array<Partial<ArrayField<FieldValues, 'id'>>>;
|
||||
append: (value: FieldArrayValue) => void;
|
||||
prepend: (value: FieldArrayValue) => void;
|
||||
remove: (index?: number | number[]) => void;
|
||||
swap: (indexA: number, indexB: number) => void;
|
||||
move: (from: number, to: number) => void;
|
||||
insert: (index: number, value: FieldArrayValue) => void;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user