# All files / src/Form/components/Field Field.tsx

45.45% Statements 15/33
0% Branches 0/8
0% Functions 0/6
48.39% Lines 15/31

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    961x
    1x
    1x
    1x

    1x
    1x
    1x
    1x
    1x

    1x

    1x

    1x

    1x

    1x

    1x
     import * as React from 'react'
    import { createUseStyles } from '@fluent-ui/styles'
    import { styles } from './Field.styled'
    import { FieldProps, FieldPropTypes, FormFieldClassProps } from '../../Form.type'
    import { Theme } from '../../../styles'

    import Typography from '../../../Typography'
    import Transition from '../../../Transition'
    import { FormContext } from '../../Form.context'
    import { createValidator } from '../../Form.validator'
    import classNames from 'classnames'

    export const name = 'FormField'

    const useStyles = createUseStyles<Theme, FormFieldClassProps>(styles, { name })

    const Field: React.FC<FieldProps> = React.forwardRef<HTMLTableRowElement, FieldProps>(
      (props, ref): React.ReactElement => {
        const { children, onChange, label, name, rules, ...rest } = props

        const { state, dispatch, descriptor } = React.useContext(FormContext)

        const [value, setValue] = React.useState(state.values[name] || '')

        const handleValueChange = React.useCallback(
          (v): void => {
            dispatch({
              type: 'onChange',
              payload: {
                [name]: v
              }
            })

            onChange ? onChange(v) : setValue(v)
          },
          [onChange, dispatch, name]
        )

        React.useEffect((): void => {
          createValidator(
            descriptor,
            state.values,
            (errors: any[]): void => {
              dispatch({ type: 'onError', payload: errors })
            }
          )
        }, [dispatch, descriptor, state.values])

        const required = React.useMemo(
          (): boolean => (rules ? !!rules.find((v): boolean => v.required === true) : false),
          [rules]
        )

        // About the error message
        const { errors } = state
        const selfError = errors[name]

        const classes = useStyles(props)
        const labelClassName = classNames(classes.label, {
          [classes.labelRequired]: required
        })

        return (
          <tr ref={ref}>
            {label && (
              <Typography variant="body1" as="td">
                <label className={labelClassName} htmlFor={name}>
                  {label}
                </label>
              </Typography>
            )}
            <td>
              {React.cloneElement(children, {
                name,
                value,
                onChange: handleValueChange,
                error: !!selfError,
                ...rest
              })}
              <Transition visible={!!selfError} wrapper={false} mountOnEnter unmountOnExit>
                <Typography variant="body2" color="error.default">
                  {selfError}
                </Typography>
              </Transition>
            </td>
          </tr>
        )
      }
    )

    Field.displayName = 'FFormField'

    Field.propTypes = FieldPropTypes

    export default Field