Avaiga / taipy

Turns Data and AI algorithms into production-ready web applications in no time.
https://www.taipy.io
Apache License 2.0
15.54k stars 1.86k forks source link

[πŸ› BUG] Multi-value slider with lov binds `value` to the post-adapter lov elements #2290

Open arcanaxion opened 14 hours ago

arcanaxion commented 14 hours ago

What went wrong? πŸ€”

Example code:

from taipy.gui import Gui
import taipy.gui.builder as tgb

aggregation_list = ["minute", "hour", "day", "week"]
selected_aggregation = [aggregation_list[0], aggregation_list[1]]

def aggregation_adapter(aggregation):
    return aggregation.title()

with tgb.Page() as page:
    tgb.text("# Adapter modifying bound value for multi-value slider", mode="md")
    tgb.slider("{selected_aggregation}", lov="{aggregation_list}", label="Aggregation", adapter=aggregation_adapter)
    tgb.text("{selected_aggregation}")

def on_change(state, var_name, var_value):
    print(var_name, type(var_value), var_value)

if __name__ == "__main__":
    gui = Gui(page=page)
    gui.run()

In develop, modifying the slider displays:

image

Seems to be a regression -- was working as expected in 4.0.1.

Expected Behavior

Values should be lowercase

Browsers

Chrome, Firefox

OS

Windows, Linux

Version of Taipy

develop

Acceptance Criteria

Code of Conduct

FredLL-Avaiga commented 10 hours ago

Does it work for single value selection ?

FredLL-Avaiga commented 10 hours ago

If you want an id different from your label, you need to specify it in your adapter:

def aggregation_adapter(aggregation):
    return (aggregation, aggregation.title())

Does that work for you @arcanaxion ?

import taipy.gui.builder as tgb
from taipy.gui import Gui

aggregation_list = ["minute", "hour", "day", "week"]
selected_aggregation = [aggregation_list[0], aggregation_list[1]]

def aggregation_adapter(aggregation):
    return (aggregation, aggregation.title())

with tgb.Page() as page:
    tgb.text("# Adapter modifying bound value for multi-value slider", mode="md")
    tgb.slider("{selected_aggregation}", lov="{aggregation_list}", label="Aggregation", adapter=aggregation_adapter)
    tgb.text("{selected_aggregation}")

def on_change(state, var_name, var_value):
    print(var_name, type(var_value), var_value)

if __name__ == "__main__":
    gui = Gui(page=page)
    gui.run(title="2290 [πŸ› BUG] Multi-value slider with lov binds value to the post-adapter lov elements")
arcanaxion commented 9 hours ago

@FredLL-Avaiga Yes, your correction works for me and it makes sense. Indeed the docs state that adapter should return a tuple.

But the inconsistency using my (wrong) method only seems to be affecting multi-value sliders:

from taipy.gui import Gui
import taipy.gui.builder as tgb

aggregation_list = ["minute", "hour", "day", "week"]
selected_aggregation_multiple = [aggregation_list[0], aggregation_list[1]]
selected_aggregation = aggregation_list[0]
selected_aggregation_selector = aggregation_list[0]

def aggregation_adapter(aggregation):
    return aggregation.title()

with tgb.Page() as page:
    tgb.text("# Adapter modifying bound value for multi-value slider", mode="md")
    tgb.slider("{selected_aggregation_multiple}", lov="{aggregation_list}", adapter=aggregation_adapter)
    tgb.text("{selected_aggregation_multiple}")

    tgb.slider("{selected_aggregation}", lov="{aggregation_list}", adapter=aggregation_adapter)
    tgb.text("{selected_aggregation}")

    tgb.selector("{selected_aggregation_selector}", lov="{aggregation_list}", adapter=aggregation_adapter)
    tgb.text("{selected_aggregation_selector}")

def on_change(state, var_name, var_value):
    print(var_name, type(var_value), var_value)

if __name__ == "__main__":
    gui = Gui(page=page)
    gui.run()

image

Probably this should either work consistently, or perhaps raise an error if the adapter is not returning a 2-element tuple.