Przeglądaj źródła

handle lov id as empty string (#2244)

* handle lov id as empty string
default unselected value is null
reflect unselection
resolves #2235

* remove unselected_value

---------

Co-authored-by: Fred Lefévère-Laoide <Fred.Lefevere-Laoide@Taipy.io>
Fred Lefévère-Laoide 6 miesięcy temu
rodzic
commit
c5946155e0

+ 11 - 11
frontend/taipy-gui/src/components/Taipy/Toggle.spec.tsx

@@ -124,34 +124,34 @@ describe("Toggle Component", () => {
             type: "SEND_UPDATE_ACTION",
         });
     });
-    it("dispatch unselected_value on deselection when allowUnselect", async () => {
+    it("dispatch nothing on deselection by default", async () => {
         const dispatch = jest.fn();
         const state: TaipyState = INITIAL_STATE;
         const { getByText } = render(
             <TaipyContext.Provider value={{ state, dispatch }}>
-                <Toggle lov={lov} updateVarName="varname" unselectedValue="uv" value="id2" allowUnselect={true} />
+                <Toggle lov={lov} updateVarName="varname" value="id2" />
             </TaipyContext.Provider>
         );
         const elt = getByText("Item 2");
         await userEvent.click(elt);
-        expect(dispatch).toHaveBeenCalledWith({
-            name: "varname",
-            payload: { value: "uv" },
-            propagate: true,
-            type: "SEND_UPDATE_ACTION",
-        });
+        expect(dispatch).not.toHaveBeenCalled();
     });
-    it("dispatch nothing on deselection by default", async () => {
+    it("dispatch null on deselection when allowUnselect", async () => {
         const dispatch = jest.fn();
         const state: TaipyState = INITIAL_STATE;
         const { getByText } = render(
             <TaipyContext.Provider value={{ state, dispatch }}>
-                <Toggle lov={lov} updateVarName="varname" unselectedValue="uv" value="id2" />
+                <Toggle lov={lov} updateVarName="varname" value="id2" allowUnselect={true} />
             </TaipyContext.Provider>
         );
         const elt = getByText("Item 2");
         await userEvent.click(elt);
-        expect(dispatch).not.toHaveBeenCalled();
+        expect(dispatch).toHaveBeenCalledWith({
+            name: "varname",
+            payload: { value: null },
+            propagate: true,
+            type: "SEND_UPDATE_ACTION",
+        });
     });
 
     describe("As Switch", () => {

+ 8 - 20
frontend/taipy-gui/src/components/Taipy/Toggle.tsx

@@ -14,26 +14,25 @@
 import React, { MouseEvent, SyntheticEvent, useCallback, useEffect, useMemo, useState } from "react";
 import Box from "@mui/material/Box";
 import Switch from "@mui/material/Switch";
-import Typography from "@mui/material/Typography";
 import ToggleButton from "@mui/material/ToggleButton";
 import ToggleButtonGroup from "@mui/material/ToggleButtonGroup";
 import Tooltip from "@mui/material/Tooltip";
+import Typography from "@mui/material/Typography";
 
+import { FormControlLabel, SxProps } from "@mui/material";
 import { createSendUpdateAction } from "../../context/taipyReducers";
-import ThemeToggle, { emptyStyle } from "./ThemeToggle";
-import { LovProps, useLovListMemo } from "./lovUtils";
 import { useClassNames, useDispatch, useDynamicProperty, useModule } from "../../utils/hooks";
-import { getCssSize, getSuffixedClassNames, getUpdateVar } from "./utils";
 import { Icon, IconAvatar } from "../../utils/icon";
-import { FormControlLabel, SxProps } from "@mui/material";
 import { getComponentClassName } from "./TaipyStyle";
+import ThemeToggle, { emptyStyle } from "./ThemeToggle";
+import { LovProps, useLovListMemo } from "./lovUtils";
+import { getCssSize, getSuffixedClassNames, getUpdateVar } from "./utils";
 
 const baseGroupSx = { verticalAlign: "middle" };
 
 interface ToggleProps extends LovProps<string> {
     style?: SxProps;
     label?: string;
-    unselectedValue?: string;
     allowUnselect?: boolean;
     mode?: string;
     isSwitch?: boolean;
@@ -49,14 +48,13 @@ const Toggle = (props: ToggleProps) => {
         propagate = true,
         lov,
         defaultLov = "",
-        unselectedValue = "",
         updateVars = "",
         valueById,
         mode = "",
         isSwitch = false,
     } = props;
     const dispatch = useDispatch();
-    const [value, setValue] = useState(props.defaultValue);
+    const [value, setValue] = useState<string | null | undefined>(props.defaultValue);
     const [bVal, setBVal] = useState(() =>
         typeof props.defaultValue === "boolean"
             ? props.defaultValue
@@ -85,7 +83,7 @@ const Toggle = (props: ToggleProps) => {
             dispatch(
                 createSendUpdateAction(
                     updateVarName,
-                    val === null ? unselectedValue : val,
+                    val,
                     module,
                     props.onChange,
                     propagate,
@@ -93,17 +91,7 @@ const Toggle = (props: ToggleProps) => {
                 )
             );
         },
-        [
-            unselectedValue,
-            updateVarName,
-            propagate,
-            dispatch,
-            updateVars,
-            valueById,
-            props.onChange,
-            props.allowUnselect,
-            module,
-        ]
+        [updateVarName, propagate, dispatch, updateVars, valueById, props.onChange, props.allowUnselect, module]
     );
 
     const changeSwitchValue = useCallback(

+ 0 - 1
taipy/gui/_renderers/factory.py

@@ -626,7 +626,6 @@ class _Factory:
                 ("hover_text", PropertyType.dynamic_string),
                 ("label",),
                 ("value_by_id", PropertyType.boolean),
-                ("unselected_value", PropertyType.string, ""),
                 ("allow_unselect", PropertyType.boolean),
                 ("on_change", PropertyType.function),
                 ("mode",),

+ 1 - 1
taipy/gui/gui.py

@@ -735,7 +735,7 @@ class Gui:
         elif rel_var and isinstance(current_value, _TaipyLovValue):  # pragma: no cover
             lov_holder = _getscopeattr_drill(self, self.__evaluator.get_hash_from_expr(rel_var))
             if isinstance(lov_holder, _TaipyLov):
-                if value:
+                if isinstance(value, str):
                     val = value if isinstance(value, list) else [value]
                     elt_4_ids = self.__adapter._get_elt_per_ids(lov_holder.get_name(), lov_holder.get())
                     ret_val = [elt_4_ids.get(x, x) for x in val]

+ 3 - 9
taipy/gui/viselements.json

@@ -275,12 +275,6 @@
                         "default_value": "False",
                         "doc": "If set, this allows de-selection and the value is set to unselected_value."
                     },
-                    {
-                        "name": "unselected_value",
-                        "type": "Any",
-                        "default_value": "None",
-                        "doc": "Value assigned to <i>value</i> when no item is selected."
-                    },
                     {
                         "name": "mode",
                         "type": "str",
@@ -1632,7 +1626,7 @@
             }
         ],
         [
-            "alert",  
+            "alert",
             {
                 "inherits": ["shared"],
                 "properties": [
@@ -1662,7 +1656,7 @@
                         "doc": "If False, the alert is hidden."
                     }
                 ]
-            }                       
+            }
         ],
         [
             "status",
@@ -1842,7 +1836,7 @@
                     }
                 ]
             }
-        ]                                       
+        ]
     ],
     "blocks": [
         [

+ 2 - 3
tests/gui/builder/control/test_toggle.py

@@ -16,14 +16,14 @@ from taipy.gui import Gui
 def test_toggle_builder(gui: Gui, helpers):
     with tgb.Page(frame=None) as page:
         tgb.toggle(theme=True)  # type: ignore[attr-defined]
-    expected_list = ["<Toggle", 'mode="theme"', 'unselectedValue=""']
+    expected_list = ["<Toggle", 'mode="theme"']
     helpers.test_control_builder(gui, page, expected_list)
 
 
 def test_toggle_allow_unselected_builder(gui: Gui, helpers):
     with tgb.Page(frame=None) as page:
         tgb.toggle(allow_unselect=True, lov="1;2")  # type: ignore[attr-defined]
-    expected_list = ["<Toggle", 'unselectedValue=""', "allowUnselect={true}"]
+    expected_list = ["<Toggle", "allowUnselect={true}"]
     helpers.test_control_builder(gui, page, expected_list)
 
 
@@ -40,7 +40,6 @@ def test_toggle_lov_builder(gui: Gui, test_client, helpers):
         "lov={_TpL_tp_TpExPr_gui_get_adapted_lov_lov_tuple_TPMDL_0_0}",
         'updateVars="lov=_TpL_tp_TpExPr_gui_get_adapted_lov_lov_tuple_TPMDL_0_0"',
         'updateVarName="_TpLv_tpec_TpExPr_x_TPMDL_0"',
-        'unselectedValue=""',
         "value={_TpLv_tpec_TpExPr_x_TPMDL_0}",
     ]
     helpers.test_control_builder(gui, page, expected_list)

+ 4 - 6
tests/gui/control/test_toggle.py

@@ -14,19 +14,19 @@ from taipy.gui import Gui
 
 def test_toggle_md(gui: Gui, helpers):
     md_string = "<|toggle|theme|>"
-    expected_list = ["<Toggle", 'mode="theme"', 'unselectedValue=""']
+    expected_list = ["<Toggle", 'mode="theme"']
     helpers.test_control_md(gui, md_string, expected_list)
 
 
 def test_toggle_width_md(gui: Gui, helpers):
     md_string = "<|toggle|theme|width=70%|>"
-    expected_list = ["<Toggle", 'mode="theme"', 'unselectedValue=""', 'width="70%"']
+    expected_list = ["<Toggle", 'mode="theme"', 'width="70%"']
     helpers.test_control_md(gui, md_string, expected_list)
 
 
 def test_toggle_allow_unselected_md(gui: Gui, helpers):
     md_string = "<|toggle|lov=1;2|allow_unselect|>"
-    expected_list = ["<Toggle", 'unselectedValue=""', "allowUnselect={true}"]
+    expected_list = ["<Toggle", "allowUnselect={true}"]
     helpers.test_control_md(gui, md_string, expected_list)
 
 
@@ -42,7 +42,6 @@ def test_toggle_lov_md(gui: Gui, test_client, helpers):
         "lov={_TpL_tp_TpExPr_gui_get_adapted_lov_lov_tuple_TPMDL_0_0}",
         'updateVars="lov=_TpL_tp_TpExPr_gui_get_adapted_lov_lov_tuple_TPMDL_0_0"',
         'updateVarName="_TpLv_tpec_TpExPr_x_TPMDL_0"',
-        'unselectedValue=""',
         "value={_TpLv_tpec_TpExPr_x_TPMDL_0}",
     ]
     helpers.test_control_md(gui, md_string, expected_list)
@@ -50,7 +49,7 @@ def test_toggle_lov_md(gui: Gui, test_client, helpers):
 
 def test_toggle_html_1(gui: Gui, helpers):
     html_string = '<taipy:toggle theme="True" />'
-    expected_list = ["<Toggle", 'mode="theme"', 'unselectedValue=""']
+    expected_list = ["<Toggle", 'mode="theme"']
     helpers.test_control_html(gui, html_string, expected_list)
 
 
@@ -66,7 +65,6 @@ def test_toggle_html_2(gui: Gui, test_client, helpers):
         "lov={_TpL_tp_TpExPr_gui_get_adapted_lov_lov_tuple_TPMDL_0_0}",
         'updateVars="lov=_TpL_tp_TpExPr_gui_get_adapted_lov_lov_tuple_TPMDL_0_0"',
         'updateVarName="_TpLv_tpec_TpExPr_x_TPMDL_0"',
-        'unselectedValue=""',
         "value={_TpLv_tpec_TpExPr_x_TPMDL_0}",
     ]
     helpers.test_control_html(gui, html_string, expected_list)