Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(enhancement?) Dropdown options update to try to keep the same displayed value if available in new options #3309

Open
shadiakiki1986 opened this issue Nov 9, 2021 · 0 comments

Comments

@shadiakiki1986
Copy link

Because of self.index = 0 in widget_selection.py#L214, an update to a dropdown's options would reset the selected option to the one at index=0.

However, if the new options list still contain the currently selected value, it would be nice to update the index such that the selected value is still the same.

Example demonstrating current status:

w_dropdown = widgets.Dropdown(options=[1,2,3], index=0)
assert w_dropdown.value==1
w_dropdown.options = [3,2,1]
assert w_dropdown.value==3 # nice if this stays at 1

Example patch (added section surrounded with >>>>>>>)

# Again, with my own patch
w_dropdown = widgets.Dropdown(options=[1,2,3], index=0)

assert w_dropdown.value==1

display(w_dropdown)

print("sleep 5 to observe any value change")
import time
time.sleep(5)

def _propagate_options(self, change):
        "Set the values and labels, and select the first option if we aren't initializing"
        options = self._options_full
        self.set_trait('_options_labels', tuple(i[0] for i in options))
        self._options_values = tuple(i[1] for i in options)
        #print(f"Options changed: {self.options} -> {self._options_values}")

        if self.index is None:
            # Do nothing, we don't want to force a selection if
            # the options list changed
            return

        if self._initializing_traits_ is not True:
            if len(options) > 0:
                # >>>>>>>>>>>>>>>>>>>>>>>>
                # try to keep the same value
                if self.value in self._options_values:
                  index_new = self._options_values.index(self.value)
                  #print(f"try to keep same value {self.value} by changing index from {self.index} to {index_new}")
                  self.index = index_new
                  return
                # >>>>>>>>>>>>>>>>>>>>>>>>
                
                if self.index == 0:
                    # Explicitly trigger the observers to pick up the new value and
                    # label. Just setting the value would not trigger the observers
                    # since traitlets thinks the value hasn't changed.
                    self._notify_trait('index', 0, 0)
                else:
                    self.index = 0
            else:
                self.index = None


# Avoid using "w_dropdown.options = ..." so as not to trigger the upstream "_propagate_options"
w_dropdown._options_full = widgets.widget_selection._make_options([3,2,1])
_propagate_options(w_dropdown, None)

assert w_dropdown.value==1 # indeed this stays 1

# Visually confirm that the displayed value is still 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant