title: Bokeh - How to have the same widget (or duplicate a widget) in two different tabs?
body: <p>I'm trying to create a widget filter (made up of <code>TextInput</code> and <code>MultiSelect</code>) that is replicated on two different Bokeh <em>Tabs</em>. The desired functionality is that filtering results should be preserved between tabs, regardless of which filter receives the text to filter off of.</p>
  
  <p>The code below(it is working code) builds the <code>Filter</code> widget which is instantiated as <code>filter1</code> and <code>filter2</code>. The callback is the <code>update</code> function which does the actual filtering and updates the <code>MultiSelect</code> part of the filter.</p>
  
  <pre><code>from bokeh.io import curdoc
  from bokeh.layouts import column, widgetbox, row, layout, gridplot
  from bokeh.models import Slider, Select, TextInput, MultiSelect
  from bokeh.models.widgets import Panel, Tabs
  import pandas as pd
  from functools import partial
  
  
  df = pd.DataFrame(["apples", "oranges", "grapes"], columns=["fruits"])
  
  
  multiselect = None
  input_box = None
  
  
  def update(widget, attr, old, new):
      print("df['fruits']: {}".format(list(df['fruits'])))
      print("{} : {} changed: Old [ {} ] -&gt; New [ {} ]".format(widget, attr, old, new))
  
      if widget == 'input':
          col_data = list(df[df['fruits'].str.contains(new)]['fruits'])
          print("col_date: {}".format(col_data))
          multiselect.update(options = sorted(list(col_data)))
  
  
  def init():
      global multiselect
      multiselect = MultiSelect(title = 'multiselect',
                                name = 'multiselect',
                                value = [],
                                options = list(df["fruits"]))
      multiselect.on_change('value', partial(update,  multiselect.name))
  
      global input_box
      input_box = TextInput(title = 'input',
                             name ='input',
                             value='Enter you choice')
      input_box.on_change('value', partial(update, input_box.name))
  
  class Filter:
      def __init__(self):
          self.multiselect = multiselect
          self.input_box = input_box
          self.widget = widgetbox(self.input_box, self.multiselect)
  
  init()
  filter1 = Filter().widget
  filter2 = Filter().widget
  
  curdoc().add_root(row(filter1, filter2))
  </code></pre>
  
  <p>The code above produces/assembles the widget as shown here:</p>
  
  <p><a href="https://i.stack.imgur.com/BQaet.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/BQaet.png" alt="enter image description here"></a></p>
  
  <p>Also, the functionality of the two mirrored filters is as desired; when text is entered in one of the boxes, the results are displayed on both filters.</p>
  
  <p>Now, and here is where I need help, I want the same filters with the same functionality <em>but</em> I need them in two different tabs; one filter in one tab and the other filter in the other tab.</p>
  
  <p>The code used to build the two tabs structure is:</p>
  
  <pre><code>p1 = Panel(child = filter1, title = "Panel1")
  
  p2 = Panel(child = filter2, title = "Panel2")
  
  tabs = Tabs(tabs=[ p1, p2 ])
  curdoc().add_root(layout(tabs))
  </code></pre>
  
  <p>On the results side, the code preserves the desired functionality <em>but</em> filters are displayed on the same page. More than that, panels/tabs are not even being built.<br>
  Any idea what's missing? (If you want to play with the code it should work right off the bat if you have bokeh installed.)</p>
  
  <p><a href="https://i.stack.imgur.com/IFoVn.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/IFoVn.png" alt="enter image description here"></a></p>