Updating the options for a Select widget based on the selection within another Select widget

I’m writing a class that has 2 pn.widgets.Select widgets. I would like to update the options in one Selector based on the other using the unique values within a pandas dataframe column. If I do the following I can get the widgets to update but when selecting a value in the second selector the value never updates (always the first one in the list of options no matter what is visibly selected)

import numpy as np
import pandas as pd
import param
import panel as pn

import configuration as cfg

pn.extension()

class TG51(param.Parameterized):

def __init__(self, **params):
    super(TG51, self).__init__(**params)
    
    self.title = pn.Row('## TG-51 Photon Worksheet')
    self.institution = 
    pn.widgets.Select(name='Institution', value='', 
    options=INSTITUTIONS)

    @param.depends('institution.value')
    def get_machines(self):
        self.machine =  
        pn.widgets.Select(name='Machine',  
        options=machine_df.loc[machine_df['Institution 
        Name'] == self.institution.value]['Machine 
        Designation'].unique().tolist())
        return self.machine

    @param.depends('machine.value')
    def machine_change_callback(self):
        # This never gets called when machine Selection 
        # is changed

   def form(self):        
       return pn.Column(self.title,
           pn.Row(self.institution, self.get_machines, 
           self.date_picker), self.physicist,
           pn.Row(self.photon_rdgs, self.photon_means), 
           pn.Row(self.electron_rdgs, 
            self.electron_means))

If I do the following I cannot figure out how to update the options in the machine Select widget directly.

class TG51(param.Parameterized):

def __init__(self, **params):
    super(TG51, self).__init__(**params)
    
    self._current_inst = None
    
    self.title = pn.Row('## TG-51 Photon Worksheet')
    
    self.institution = 
        pn.widgets.Select(name='Institution', value='', 
        options=INSTITUTIONS)
    self.machine = pn.widgets.Select(name='Machine', 
        options=machine_df.loc[machine_df['Institution 
         Name'] == self.institution.value]['Machine 
         Designation'].unique().tolist())
    
   # This method doesn't work at all
   @param.depends('institution.value')
   def update_machines(self):
        self.machine.options = 
            machine_df.loc[machine_df['Institution Name'] 
            == self.institution.value]['Machine 
            Designation'].unique().tolist()

I would like to be able to update the options for the dropdown in place so that I can then watch for changes in the machine selection widget as well. Changing out the entire widget in the call back as in the first option works but again it is replacing the widget completely and therefore it seems to always want to select the first option in the list causing the interface to be out of sync when selections are made in the machine selection widget (i.e. widget shows Machine 2 selected but machine.value reports Machine 1 when accessed and no selection change calbacks are ever called upon changing the selection)

Thanks,
Mike

1 Like

Mike,

I haven’t had a chance to look through your code in detail, but I think you may be mixing the Reactive functions and the Parameterized Class approach.

You are creating parameterized classes, but then not defining any parameters.

It also looks like your decorators are mixing the syntax of the two approaches. If you are writing a function that depends on a parameter, you should use the @param.depends('parameter_name'), where you have just the parameter name in quotes without the .value and the decorator is from param.

If you are using the reactive approach and defining a widget and a function that depends on the state of the widget, then you would use @pn.depends(widget_name.param.value), where the decorator is from panel and you don’t use quotes within the parentheses.

I’m referencing the API documentation as I write this, so that might be helpful to you as well.

Also, I think I worked through a somewhat similar issue, so you might look at my question about linking list selectors.

Hope this is helpful info.

1 Like