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