Reputation: 3443
I am using ipywidgets to create a dashboard.
I create a bunch of buttons using a loop:
from ipywidgets import GridspecLayout
grid = GridspecLayout(4, 3)
def create_expanded_button(description, button_style):
return Button(description=description, button_style=button_style, layout=Layout(height='auto', width='auto'))
for i in range(4):
for j in range(3):
grid[i, j] = create_expanded_button('Button {} - {}'.format(i, j), 'warning')
grid
This is the code in the documentation. With such a code you create a dashboard with 16 buttons:
The question is what is the strategy as to how to handle every on_click methods of the buttons since all the buttons are called the same. Do the buttons have a kind of 'id'?
imagine that by clicking every button I want to fetch a particular data online. how to proceed?
thanks.
Upvotes: 2
Views: 7544
Reputation: 2347
Unfortunately, the Button widget is lacking an 'id' parameter. Fortunately, using the partial
function from functools, we are able to pass additional arguments to the on_button_clicked
callback method. In this example I am simply adding an id
and otherArg
argument to show how to add more than one argument.
import ipywidgets as widgets
from IPython.display import display
from functools import partial
def on_button_clicked(btn, id="some_default_ID", otherArg=""):
print(id,"passed into this method from the",btn.description)
print(otherArg)
button21 = widgets.Button(description="Click me (button21)")
button21.on_click(partial(on_button_clicked, id="R21", otherArg="And this other argument"))
display(button21)
Clicking the button would print the following to the console:
R21 passed into this method from the Click me (button21)
And this other argument
On a side note, you can also pass other widgets as arguments to the click method. For instance, below is a saveCurationEntryClick
method used to check the state (values) of description and datatime fields when we click the Save entry
button.
def saveCurationEntryClick(self, btn, d, t):
print("Current description is:",d.value,"and the time is",t.value)
itemsArray=[]
txtDesc = widgets.Textarea(
value='',
placeholder='Enter curation entry description/details',
description='Log entry:',
disabled=False
)
itemsArray.append(txtDesc)
dteTime = widgets.DatetimePicker(
description='Pick a Date/Time',
value=self.getCurrentTime(),
disabled=False
)
itemsArray.append(dteTime)
btn = widgets.Button(
description='Save entry',
disabled=False,
button_style='',
tooltip='Add curation log entry',
icon='check' # (FontAwesome names without the `fa-` prefix)
)
btn.on_click(partial(self.saveCurationEntryClick, d=txtDesc, t=dteTime))
itemsArray.append(btn)
widgets.VBox(itemsArray)
Upvotes: 0
Reputation: 5575
How about defining your APIs and calling functions first, then iterating through those creating buttons?
from ipywidgets import GridspecLayout, Button
grid = GridspecLayout(3, 1)
def call_api_1(button):
print('calling_api_1')
def call_api_2(button):
print('calling_api_2')
def call_api_3(button):
print('calling_api_3')
api_dict = {
'API 1': call_api_1,
'API 2': call_api_2,
'API 3': call_api_3,
}
for index, (api_name, func) in enumerate(api_dict.items()):
button = Button(description = api_name)
button.on_click(func)
grid[index,0] = button
grid
Upvotes: 0
Reputation: 195
Try this:
def on_btn_click(btn):
if btn.description == 'Button 0 - 0':
# do something on Button 0 - 0 click
elif btn.description == 'Button 0 - 1':
# do something on Button 0 - 1 click
...
for i in range(4):
for j in range(3):
grid[i,j].on_click(on_btn_click)
Upvotes: 1