Skip to content

Commit

Permalink
fix(core/notification): stop infinite-looping on custom notification …
Browse files Browse the repository at this point in the history
…input (#8267)
  • Loading branch information
Erik Munson committed May 7, 2020
1 parent 31dc01e commit a3abc33
Showing 1 changed file with 47 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,56 @@ import {
validationClassName,
} from 'core/presentation';

const { useEffect, useState } = React;
const { useEffect } = React;

interface IWhenChecklistInputProps
extends IFormInputProps,
OmitControlledInputPropsFrom<React.InputHTMLAttributes<any>> {
options?: IWehnChecklistInputOption[];
options?: IWhenChecklistInputOption[];
}

export interface IWehnChecklistInputOption {
interface IWhenChecklistInputOption {
label: string;
value: string;
additionalFields?: React.ReactNode;
}

interface ICheckBoxProps {
option: IWhenChecklistInputOption;
selected: string[];
onChange: (event: React.ChangeEvent<string[]>) => any;
inputClassName: string;
inputProps: any;
}

function CheckBox({ option, selected, onChange, inputClassName, inputProps }: ICheckBoxProps) {
function handleChange({ target }: React.ChangeEvent<HTMLInputElement>) {
const newValue = !selected.includes(target.value)
? selected.concat(target.value)
: selected.filter((v: string) => v !== target.value);
onChange(createFakeReactSyntheticEvent({ value: newValue, name: target.name }));
}

return (
<>
<label className="clickable" key={option.value}>
<input
className={inputClassName}
type="checkbox"
value={option.value}
onChange={handleChange}
checked={selected.includes(option.value)}
{...inputProps}
/>
{option.label}
</label>
{selected.includes(option.value) && option.additionalFields}
</>
);
}

export function WhenChecklistInput(props: IWhenChecklistInputProps) {
const { value, validation, inputClassName, options, onChange, ...otherProps } = props;
const { value, validation, inputClassName, options, onChange, ...inputProps } = props;

// Naively call the the field's onBlur handler
// This is what Formik uses to mark the field as touched
Expand All @@ -32,47 +66,20 @@ export function WhenChecklistInput(props: IWhenChecklistInputProps) {
}
useEffect(touchField, []);

const className = `${orEmptyString(inputClassName)} ${validationClassName(validation)}`;

const selectedValues = value || [];
const isChecked = (checkboxValue: any) => selectedValues.includes(checkboxValue);

function CheckBox(checkboxProps: { option: IWehnChecklistInputOption }) {
const [checked, setChecked] = useState(isChecked(checkboxProps.option.value));
const { option } = checkboxProps;

function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
const selected = e.target.value;
const alreadyHasValue = isChecked(selected);
const newValue = !alreadyHasValue ? selectedValues.concat(selected) : value.filter((v: string) => v !== selected);
onChange(createFakeReactSyntheticEvent({ value: newValue, name: e.target.name }));
setChecked(isChecked(selected));
}

return (
<>
<label className="clickable" key={option.value}>
<input
className={className}
type="checkbox"
value={option.value}
onChange={handleChange}
checked={checked}
{...otherProps}
/>
{option.label}
</label>
{checked && option.additionalFields}
</>
);
}
const selectedValues: string[] = value || [];

return (
<div className="checkbox">
<ul className="checklist">
{options.map((option: IWehnChecklistInputOption) => (
{options.map((option: IWhenChecklistInputOption) => (
<li key={option.label}>
<CheckBox option={option} />
<CheckBox
option={option}
selected={selectedValues}
inputClassName={`${orEmptyString(inputClassName)} ${validationClassName(validation)}`}
inputProps={inputProps}
onChange={onChange}
/>
</li>
))}
</ul>
Expand Down

0 comments on commit a3abc33

Please sign in to comment.