JFerro
JFerro

Reputation: 3443

adding on_click methods to buttons created with ipywidgets

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:

enter image description here

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

Answers (3)

w. Patrick Gale
w. Patrick Gale

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)

enter image description here

Upvotes: 0

ac24
ac24

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

lonsty
lonsty

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

Related Questions