17573: Adds redux-form controlled multi-checkbox selection component.
[arvados-workbench2.git] / src / components / checkbox-field / checkbox-field.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React from 'react';
6 import { WrappedFieldProps } from 'redux-form';
7 import {
8     FormControlLabel,
9     Checkbox,
10     FormControl,
11     FormGroup,
12     FormLabel,
13     FormHelperText
14 } from '@material-ui/core';
15
16 export const CheckboxField = (props: WrappedFieldProps & { label?: string }) =>
17     <FormControlLabel
18         control={
19             <Checkbox
20                 checked={props.input.value}
21                 onChange={props.input.onChange}
22                 disabled={props.meta.submitting}
23                 color="primary" />
24         }
25         label={props.label}
26     />;
27
28 type MultiCheckboxFieldProps = {
29     items: string[];
30     label?: string;
31     minSelection?: number;
32     maxSelection?: number;
33     helperText?: string;
34     rowLayout?: boolean;
35 }
36
37 export const MultiCheckboxField = (props: WrappedFieldProps & MultiCheckboxFieldProps) => {
38     const isValid = (items: string[]) => (items.length >= (props.minSelection || 0)) &&
39         (items.length <= (props.maxSelection || items.length));
40     return <FormControl error={!isValid(props.input.value)}>
41         <FormLabel component='label'>{props.label}</FormLabel>
42         <FormGroup row={props.rowLayout}>
43         { props.items.map((item, idx) =>
44             <FormControlLabel
45                 control={
46                     <Checkbox
47                         key={idx}
48                         name={`${props.input.name}[${idx}]`}
49                         value={item}
50                         checked={props.input.value.indexOf(item) !== -1}
51                         onChange={e => {
52                             const newValue = [...props.input.value];
53                             if (e.target.checked) {
54                                 newValue.push(item);
55                             } else {
56                                 newValue.splice(newValue.indexOf(item), 1);
57                             }
58                             if (!isValid(newValue)) { return; }
59                             return props.input.onChange(newValue);
60                         }}
61                         disabled={props.meta.submitting}
62                         color="primary" />
63                 }
64                 label={item} />) }
65         </FormGroup>
66         <FormHelperText>{props.helperText}</FormHelperText>
67     </FormControl> };