Skip to content

Commit

Permalink
Added the action_on_blur property to 'input' and 'number'
Browse files Browse the repository at this point in the history
  • Loading branch information
FabienLelaquais committed Dec 2, 2024
1 parent 613265e commit 086f946
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 119 deletions.
126 changes: 67 additions & 59 deletions frontend/taipy-gui/src/components/Taipy/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ const getActionKeys = (keys?: string): string[] => {
const ak = (
keys
? keys
.split(";")
.map((v) => v.trim().toLowerCase())
.filter((v) => AUTHORIZED_KEYS.some((k) => k.toLowerCase() === v))
.split(";")
.map((v) => v.trim().toLowerCase())
.filter((v) => AUTHORIZED_KEYS.some((k) => k.toLowerCase() === v))
: []
).map((v) => AUTHORIZED_KEYS.find((k) => k.toLowerCase() == v) as string);
return ak.length > 0 ? ak : [AUTHORIZED_KEYS[0]];
Expand Down Expand Up @@ -63,6 +63,7 @@ const Input = (props: TaipyInputProps) => {
onAction,
onChange,
multiline = false,
actionOnBlur = false,
linesShown = 5,
} = props;

Expand All @@ -85,9 +86,9 @@ const Input = (props: TaipyInputProps) => {
() =>
props.width
? {
...numberSx,
maxWidth: getCssSize(props.width),
}
...numberSx,
maxWidth: getCssSize(props.width),
}
: numberSx,
[props.width]
);
Expand Down Expand Up @@ -139,19 +140,26 @@ const Input = (props: TaipyInputProps) => {
);

const handleBlur = useCallback(
(e: React.FocusEvent<HTMLInputElement>) => {
const val = e.target.value;
if (changeDelay > 0 && delayCall.current > 0) {
clearTimeout(delayCall.current);
delayCall.current = -1;
dispatch(createSendUpdateAction(updateVarName, val, module, onChange, propagate));
} else if (changeDelay === -1) {
(evt: React.FocusEvent<HTMLInputElement>) => {
let val = (type === "number")
? Number(evt.currentTarget.querySelector("input")?.value)
: (multiline
? evt.currentTarget.querySelector("textarea")?.value
: evt.currentTarget.querySelector("input")?.value)
;
if (delayCall.current > 0) {
if (changeDelay > 0) {
clearTimeout(delayCall.current);
delayCall.current = -1;
}
dispatch(createSendUpdateAction(updateVarName, val, module, onChange, propagate));
}
onAction && dispatch(createSendActionNameAction(id, module, onAction, "Tab", updateVarName, val));
evt.preventDefault();
},
[dispatch, updateVarName, module, onChange, propagate, changeDelay]
);

const handleAction = useCallback(
(evt: KeyboardEvent<HTMLDivElement>) => {
if (evt.shiftKey && type === "number") {
Expand Down Expand Up @@ -279,51 +287,51 @@ const Input = (props: TaipyInputProps) => {
() =>
type == "number"
? {
htmlInput: {
step: step ? step : 1,
min: min,
max: max,
},
input: {
endAdornment: (
<div style={verticalDivStyle}>
<IconButton
aria-label="Increment value"
size="small"
onMouseDown={handleUpStepperMouseDown}
disabled={!active}
>
<ArrowDropUpIcon fontSize="inherit" />
</IconButton>
<IconButton
aria-label="Decrement value"
size="small"
onMouseDown={handleDownStepperMouseDown}
disabled={!active}
>
<ArrowDropDownIcon fontSize="inherit" />
</IconButton>
</div>
),
},
}
htmlInput: {
step: step ? step : 1,
min: min,
max: max,
},
input: {
endAdornment: (
<div style={verticalDivStyle}>
<IconButton
aria-label="Increment value"
size="small"
onMouseDown={handleUpStepperMouseDown}
disabled={!active}
>
<ArrowDropUpIcon fontSize="inherit" />
</IconButton>
<IconButton
aria-label="Decrement value"
size="small"
onMouseDown={handleDownStepperMouseDown}
disabled={!active}
>
<ArrowDropDownIcon fontSize="inherit" />
</IconButton>
</div>
),
},
}
: type == "password"
? {
htmlInput: { autoComplete: "current-password" },
input: {
endAdornment: (
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
edge="end"
>
{showPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
),
},
}
: undefined,
? {
htmlInput: { autoComplete: "current-password" },
input: {
endAdornment: (
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
edge="end"
>
{showPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
),
},
}
: undefined,
[
active,
type,
Expand Down Expand Up @@ -357,8 +365,8 @@ const Input = (props: TaipyInputProps) => {
id={id}
slotProps={inputProps}
label={props.label}
onBlur={handleBlur}
onChange={handleInput}
onBlur={actionOnBlur ? handleBlur : undefined}
disabled={!active}
onKeyDown={handleAction}
multiline={multiline}
Expand Down
1 change: 1 addition & 0 deletions frontend/taipy-gui/src/components/Taipy/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export interface TaipyInputProps extends TaipyActiveProps, TaipyChangeProps, Tai
changeDelay?: number;
onAction?: string;
actionKeys?: string;
actionOnBlur?: boolean;
multiline?: boolean;
linesShown?: number;
width?: string | number;
Expand Down
2 changes: 2 additions & 0 deletions taipy/gui/_renderers/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ class _Factory:
("action_keys",),
("label",),
("change_delay", PropertyType.number, gui._get_config("change_delay", None)),
("action_on_blur", PropertyType.boolean, False),
("multiline", PropertyType.boolean, False),
("lines_shown", PropertyType.number, 5),
("width", PropertyType.string_or_number),
Expand Down Expand Up @@ -434,6 +435,7 @@ class _Factory:
("on_action", PropertyType.function),
("label",),
("change_delay", PropertyType.number, gui._get_config("change_delay", None)),
("action_on_blur", PropertyType.boolean, False),
("width", PropertyType.string_or_number),
]
),
Expand Down
6 changes: 3 additions & 3 deletions taipy/gui/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -1155,9 +1155,9 @@ def set_unsupported_data_converter(converter: t.Optional[t.Callable[[t.Any], t.A
Arguments:
converter: A function that converts a value with an unsupported data type (the only
parameter to the function) into data with a supported data type (the returned value
from the function).</br>
If set to `None`, it removes any existing converter.
parameter to the function) into data with a supported data type (the returned value
from the function).</br>
If set to `None`, it removes any existing converter.
"""
Gui.__unsupported_data_converter = converter

Expand Down
Loading

0 comments on commit 086f946

Please sign in to comment.