Skip to content

Commit

Permalink
fix(FormRenderer): Fix the cosmetic issue on the FieldArray (#308)
Browse files Browse the repository at this point in the history
* fix(FormRenderer): Fix the cosmetic issue on the FieldArray

* chore: Refactor and remove the extra stories

* chore: Fix the header key
  • Loading branch information
jessieweiyi authored Aug 17, 2021
1 parent 25da626 commit baca5d7
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@
See the License for the specific language governing permissions and
limitations under the License. *
******************************************************************************************************************** */
import React, { FunctionComponent, useMemo } from 'react';
import React, { FunctionComponent, useMemo, useCallback, ReactNode } from 'react';
import { Field } from '@data-driven-forms/react-form-renderer';
import useFormApi from '@data-driven-forms/react-form-renderer/use-form-api';
import { v4 as uuidv4 } from 'uuid';
import Box from '../../../../../../layouts/Box';
import Button from '../../../../../Button';
import ColumnLayout, { Column } from '../../../../../../layouts/ColumnLayout';
import { Grid } from '../../../../../../layouts';
import Grid from '../../../../../../layouts/Grid';
import Typography from '@material-ui/core/Typography';
import InputLabel from '@material-ui/core/InputLabel';

export interface FieldArrayItemProps {
fields?: Field[];
Expand All @@ -33,6 +34,7 @@ export interface FieldArrayItemProps {
showError?: boolean;
isReadOnly: boolean;
layout?: 'grid' | 'column';
collapse: boolean;
}

const FieldArrayItem: FunctionComponent<FieldArrayItemProps> = ({
Expand All @@ -44,59 +46,108 @@ const FieldArrayItem: FunctionComponent<FieldArrayItemProps> = ({
showError,
isReadOnly,
layout,
collapse,
}) => {
const formOptions = useFormApi();

const getFieldKey = useCallback((fieldName: string) => `${name}.${fieldName}`, [name]);

const editedFields = useMemo(() => {
return fields.map((field) => {
const computedName = field.name ? `${name}.${field.name}` : uuidv4();
return {
...field,
showError,
name: computedName,
key: computedName,
name: getFieldKey(field.name),
key: getFieldKey(field.name),
stretch: true,
label: fieldIndex === 0 ? field.label : null,
label: collapse && field.label,
description: collapse && field.description,
};
});
}, [fields, name, fieldIndex, showError]);
}, [fields, showError, collapse, getFieldKey]);

const getBox = (field: Field) => (
<Box width="100%" pr={1}>
{formOptions.renderForm([field])}
</Box>
const getBox = useCallback(
(field: Field) => (
<Box width="100%" pr={1}>
{formOptions.renderForm([field])}
</Box>
),
[formOptions]
);

return (
<Box display="flex">
<Box flexGrow={1}>
{layout === 'grid' ? (
<Grid container>
{editedFields.map((field) => (
<Grid item key={field.key} xs={3}>
{getBox(field)}
</Grid>
))}
</Grid>
) : (
<ColumnLayout renderDivider={false}>
{editedFields.map((field) => (
<Column key={field.key}>{getBox(field)}</Column>
))}
</ColumnLayout>
const getHeader = useCallback(
(field: Field) => (
<Box>
{field.label && <InputLabel htmlFor={getFieldKey(field.name)}>{field.label}</InputLabel>}
{field.description && (
<Typography variant="subtitle1" component="div">
{field.description}
</Typography>
)}
</Box>
{!isReadOnly && (
<Box display="flex" alignItems="flex-start" pt={fieldIndex === 0 ? 2.5 : 0.5}>
<Button
onClick={() => {
onRemove(fieldIndex);
}}
>
{removeLabel}
</Button>
),
[getFieldKey]
);

const renderRow = useCallback(
(list: Field[], getContent: (field: Field) => ReactNode, isHeaderRow = false) => {
const buttonBoxProps = isHeaderRow
? {
visibility: 'hidden',
height: '1px',
}
: collapse
? {
display: 'flex',
alignItems: 'center',
}
: {
display: 'flex',
alignItems: 'flex-start',
pt: 0.3,
};
const getKey = (field: Field) => (isHeaderRow ? `${field.name}-header` : field.key);
return (
<Box display="flex">
<Box flexGrow={1}>
{layout === 'grid' ? (
<Grid container>
{list.map((field) => (
<Grid item key={getKey(field)} xs={3}>
{getContent(field)}
</Grid>
))}
</Grid>
) : (
<ColumnLayout renderDivider={false}>
{list.map((field) => (
<Column key={getKey(field)}>{getContent(field)}</Column>
))}
</ColumnLayout>
)}
</Box>
{!isReadOnly && (
<Box {...buttonBoxProps}>
<Button
onClick={() => {
onRemove(fieldIndex);
}}
>
{removeLabel}
</Button>
</Box>
)}
</Box>
)}
</Box>
);
},
[isReadOnly, removeLabel, onRemove, layout, collapse, fieldIndex]
);

return (
<>
{fieldIndex === 0 && !collapse && renderRow(fields, getHeader, true)}
{renderRow(editedFields, getBox)}
</>
);
};

Expand Down
6 changes: 5 additions & 1 deletion src/components/FormRenderer/components/FieldArray/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
limitations under the License. *
******************************************************************************************************************** */
import React, { FunctionComponent } from 'react';
import useMediaQuery from '@material-ui/core/useMediaQuery';
import useTheme from '@material-ui/core/styles/useTheme';
import useFieldApi, { UseFieldApiConfig } from '@data-driven-forms/react-form-renderer/use-field-api';
import { FieldArray as FieldArrayBase } from '@data-driven-forms/react-form-renderer';
import FormField from '../../../FormField';
Expand Down Expand Up @@ -48,10 +50,11 @@ const FieldArrayMapping: FunctionComponent<UseFieldApiConfig> = (props) => {
input,
isReadOnly = false,
} = useFieldApi(props);

const controlId = useUniqueId(input.name);
const errorText = getErrorText(validateOnMount, submitFailed, showError, error);
const renderedButtonLabels = { ...DEFAULT_BUTTON_LABELS, ...buttonLabels };
const theme = useTheme();
const matched = useMediaQuery(theme.breakpoints.down('xs'));

return (
<FormField
Expand Down Expand Up @@ -81,6 +84,7 @@ const FieldArrayMapping: FunctionComponent<UseFieldApiConfig> = (props) => {
minItems={minItems}
removeLabel={renderedButtonLabels.remove}
isReadOnly={isReadOnly}
collapse={matched}
/>
);
})}
Expand Down
5 changes: 4 additions & 1 deletion src/components/FormRenderer/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,10 @@ export const FieldArray = () => {
defaultItem: {
key: 'key',
value: 'value',
type: 'type1',
type: {
label: 'Type 1',
value: 'type1',
},
},
validate: [
{
Expand Down
1 change: 0 additions & 1 deletion src/components/Multiselect/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ const Multiselect: FunctionComponent<MultiselectProps> = ({
{...params}
variant="outlined"
size="small"
margin="normal"
name={name}
InputProps={{
'aria-required': ariaRequired,
Expand Down
4 changes: 4 additions & 0 deletions src/themes/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,10 @@ export const getTheme = (fontFamily?: string): ThemeOptions => ({
adornedEnd: {
paddingRight: '0px',
},
inputMarginDense: {
paddingTop: '3px',
paddingBottom: '4px',
},
},
MuiInputBase: {
root: {
Expand Down

0 comments on commit baca5d7

Please sign in to comment.