WEBAPP: Поддержка пересчёта диалогов для P8PDialog и P8PInput
This commit is contained in:
parent
c66216e47b
commit
dae416cd83
@ -26,20 +26,36 @@ const P8P_DIALOG_WIDTH = {
|
|||||||
XL: "xl"
|
XL: "xl"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//-----------------------
|
||||||
|
//Вспомогательные функции
|
||||||
|
//-----------------------
|
||||||
|
|
||||||
|
//Формирование объекта вида {ключ: значение} из текущего состояния элементов ввода формы
|
||||||
|
const buildFormValues = inputsState =>
|
||||||
|
inputsState.reduce((res, input) => ({ ...res, [input.name]: input.value == undefined ? null : input.value }), {});
|
||||||
|
|
||||||
//-----------
|
//-----------
|
||||||
//Тело модуля
|
//Тело модуля
|
||||||
//-----------
|
//-----------
|
||||||
|
|
||||||
//Диалог
|
//Диалог
|
||||||
const P8PDialog = ({ title, width, fullWidth, inputs = [], children, onOk, onCancel, onClose }) => {
|
const P8PDialog = ({ title, width, fullWidth, inputs, children, onOk, onCancel, onClose, onInputChange }) => {
|
||||||
//Состояние диалога
|
//Состояние элементов ввода диалога
|
||||||
const [state, setState] = useState({});
|
const [inputsState, setInputsState] = useState([]);
|
||||||
|
|
||||||
//При изменении элемента ввода
|
//При изменении элемента ввода
|
||||||
const handleInputChange = (name, value) => setState(pv => ({ ...pv, [name]: value }));
|
const handleInputChange = (name, value) => {
|
||||||
|
//Если есть функция пересчета формы - вызовем её
|
||||||
|
const doNotChangeInputsState = onInputChange ? onInputChange(name, value, inputsState) : false;
|
||||||
|
//И ориентируясь на то, пересчитала ли она элементы ввода обновим собственное состояние.
|
||||||
|
//Если функция пересчета вернула "true", значит она пересчитала что-то, тогда новые настройки элементов придут через свойство inputs и будут обработаны в useEffect ниже.
|
||||||
|
//Следовательно, и нам здесь не надо состояние выставлять, т.к. всё будет перезаписано useEffectом.
|
||||||
|
if (!doNotChangeInputsState)
|
||||||
|
setInputsState(pv => pv.reduce((accum, cur) => [...accum, { ...cur, value: cur.name === name ? value : cur.value }], []));
|
||||||
|
};
|
||||||
|
|
||||||
//При нажатии на "ОК" диалога
|
//При нажатии на "ОК" диалога
|
||||||
const handleOk = () => onOk && onOk(state);
|
const handleOk = () => onOk && onOk(buildFormValues(inputsState));
|
||||||
|
|
||||||
//При нажатии на "Отмена" диалога
|
//При нажатии на "Отмена" диалога
|
||||||
const handleCancel = () => onCancel && onCancel();
|
const handleCancel = () => onCancel && onCancel();
|
||||||
@ -47,20 +63,23 @@ const P8PDialog = ({ title, width, fullWidth, inputs = [], children, onOk, onCan
|
|||||||
//При нажатии на "Закрыть" диалога
|
//При нажатии на "Закрыть" диалога
|
||||||
const handleClose = () => (onClose ? onClose() : onCancel ? onCancel() : null);
|
const handleClose = () => (onClose ? onClose() : onCancel ? onCancel() : null);
|
||||||
|
|
||||||
//При подключении к старнице
|
//При изменении полей для ввода
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setState(inputs.reduce((res, input) => ({ ...res, [input.name]: input.value == undefined ? null : input.value }), {}));
|
if (inputs && Array.isArray(inputs) && inputs.length > 0) setInputsState(inputs.map(input => ({ ...input })));
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
}, [inputs]);
|
||||||
}, []);
|
|
||||||
|
//Расчет объектного представления текущих значений формы
|
||||||
|
const formValues = buildFormValues(inputsState);
|
||||||
|
|
||||||
//Формирование представления
|
//Формирование представления
|
||||||
return (
|
return (
|
||||||
<Dialog onClose={handleClose} open {...{ ...(width ? { maxWidth: width } : {}), ...(fullWidth === true ? { fullWidth: true } : {}) }}>
|
<Dialog onClose={handleClose} open {...{ ...(width ? { maxWidth: width } : {}), ...(fullWidth === true ? { fullWidth: true } : {}) }}>
|
||||||
<DialogTitle>{title}</DialogTitle>
|
<DialogTitle>{title}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
{inputs.map((input, i) => (
|
{inputsState.map((input, i) => (
|
||||||
<P8PInput key={i} {...input} value={state[input.name]} formValues={state} onChange={handleInputChange} />
|
<P8PInput key={i} {...input} formValues={formValues} onChange={handleInputChange} />
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{children}
|
{children}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
@ -81,7 +100,8 @@ P8PDialog.propTypes = {
|
|||||||
children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
|
children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
|
||||||
onOk: PropTypes.func,
|
onOk: PropTypes.func,
|
||||||
onCancel: PropTypes.func,
|
onCancel: PropTypes.func,
|
||||||
onClose: PropTypes.func
|
onClose: PropTypes.func,
|
||||||
|
onInputChange: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------
|
//----------------
|
||||||
|
|||||||
@ -35,26 +35,24 @@ const P8P_INPUT = {
|
|||||||
|
|
||||||
//Поле ввода
|
//Поле ввода
|
||||||
const P8PInput = ({ name, value, label, onChange, dictionary, list, type, freeSolo = false, disabled = false, formValues, ...other }) => {
|
const P8PInput = ({ name, value, label, onChange, dictionary, list, type, freeSolo = false, disabled = false, formValues, ...other }) => {
|
||||||
//Значение элемента
|
//Значение и тип элемента
|
||||||
const [currentValue, setCurrentValue] = useState(value);
|
const [current, setCurrent] = useState({ type: undefined, value: "" });
|
||||||
|
|
||||||
//При получении нового значения из вне
|
//При получении нового значения или типа из вне
|
||||||
useEffect(() => {
|
useEffect(() => setCurrent({ value, type }), [type, value]);
|
||||||
setCurrentValue(value);
|
|
||||||
}, [value]);
|
|
||||||
|
|
||||||
//Выбор значения из словаря
|
//Выбор значения из словаря
|
||||||
const handleDictionaryClick = () => dictionary && dictionary(formValues, res => (res ? res.map(i => handleChangeByName(i.name, i.value)) : null));
|
const handleDictionaryClick = () => dictionary && dictionary(formValues, res => (res ? res.map(i => handleChangeByName(i.name, i.value)) : null));
|
||||||
|
|
||||||
//Изменение значения элемента (по событию)
|
//Изменение значения элемента (по событию)
|
||||||
const handleChange = e => {
|
const handleChange = e => {
|
||||||
setCurrentValue(e.target.value);
|
setCurrent(pv => ({ ...pv, value: e.target.value }));
|
||||||
if (onChange) onChange(e.target.name, e.target.value);
|
if (onChange) onChange(e.target.name, e.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
//Изменение значения элемента (по имени и значению)
|
//Изменение значения элемента (по имени и значению)
|
||||||
const handleChangeByName = (targetName, value) => {
|
const handleChangeByName = (targetName, value) => {
|
||||||
if (targetName === name) setCurrentValue(value);
|
if (targetName === name) setCurrent(pv => ({ ...pv, value }));
|
||||||
if (onChange) onChange(targetName, value);
|
if (onChange) onChange(targetName, value);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -69,7 +67,7 @@ const P8PInput = ({ name, value, label, onChange, dictionary, list, type, freeSo
|
|||||||
name={name}
|
name={name}
|
||||||
freeSolo
|
freeSolo
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
inputValue={currentValue ? currentValue : ""}
|
inputValue={current.value ? current.value : ""}
|
||||||
onChange={(event, newValue) => handleChangeByName(name, newValue)}
|
onChange={(event, newValue) => handleChangeByName(name, newValue)}
|
||||||
onInputChange={(event, newInputValue) => handleChangeByName(name, newInputValue)}
|
onInputChange={(event, newInputValue) => handleChangeByName(name, newInputValue)}
|
||||||
options={list}
|
options={list}
|
||||||
@ -85,7 +83,7 @@ const P8PInput = ({ name, value, label, onChange, dictionary, list, type, freeSo
|
|||||||
id={name}
|
id={name}
|
||||||
name={name}
|
name={name}
|
||||||
label={label}
|
label={label}
|
||||||
value={[undefined, null].includes(currentValue) ? "" : currentValue}
|
value={[undefined, null].includes(current.value) ? "" : current.value}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
displayEmpty
|
displayEmpty
|
||||||
@ -100,13 +98,13 @@ const P8PInput = ({ name, value, label, onChange, dictionary, list, type, freeSo
|
|||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<InputLabel {...(type == "date" ? { shrink: true } : {})} htmlFor={name}>
|
<InputLabel {...(current.type == "date" ? { shrink: true } : {})} htmlFor={name}>
|
||||||
{label}
|
{label}
|
||||||
</InputLabel>
|
</InputLabel>
|
||||||
<Input
|
<Input
|
||||||
id={name}
|
id={name}
|
||||||
name={name}
|
name={name}
|
||||||
value={currentValue ? currentValue : ""}
|
value={current.value ? current.value : ""}
|
||||||
endAdornment={
|
endAdornment={
|
||||||
dictionary ? (
|
dictionary ? (
|
||||||
<InputAdornment position="end">
|
<InputAdornment position="end">
|
||||||
@ -116,7 +114,7 @@ const P8PInput = ({ name, value, label, onChange, dictionary, list, type, freeSo
|
|||||||
</InputAdornment>
|
</InputAdornment>
|
||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
{...(type ? { type } : {})}
|
{...(current.type ? { type: current.type } : {})}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user