How to programmatically enable or disable components?

Hi,

I am new to Gradio and I am struggling to figure out how to enable or disable (i.e. change the interactive flag) of component B based on events in component A.

My question can be best illustrated in code:

import gradio as gr                                                             

def b_clicked(o):
    # how to enable the other button "o"?
    pass

with gr.Blocks() as app:
    b = gr.Button("Enable the other obutton", interactive = True)
    o = gr.Button("Other Button", interactive = False)
    b.click(fn = b_clicked, inputs = o)

if __name__ == "__main__":
    app.launch()

I know there is a gr.update() method, which in theory should allow to update the value of the interactive setting, but I failed to understand how to reference another component. In def b_clicked(o) the o parameter is a string and not an object.

I tried wrapping the whole code into a class, thus gaining access to the actual button objects via self.b and self.o and then trying something like:

def b_clicked(self):
    self.o.update(interactive = True)

However nothing changed on the screen. I also tried to add an app.render() after the update, but this did not help either.

What is the proper way to accomplish that?

Kind regards,
Jin

1 Like

Enjoy, I hope it’s not too late

import gradio as gr                                                             

def b_clicked(o):
    return gr.Button.update(interactive=True)
    

with gr.Blocks() as app:
    b = gr.Button("Enable the other obutton", interactive = True)
    o = gr.Button("Other Button", interactive = False)
    b.click(fn = b_clicked, inputs = b, outputs = o)

if __name__ == "__main__":
    app.launch()
3 Likes

Hi @Bigiman,

thank you, this works as expected! It’s never too late :slight_smile: Even if I did not use Gradio for my project in the end and switched to Glade + GTK (not due to this issue, but due to how Gradio handles long videos), I still appreciate the answer, so that I know how to do it properly in the future.

I guess I failed to understand the whole concept behind it, my assumption was that the handler gets instances of other components as parameters, allowing me to access them. In your example however, the o parameter is not being used in the handler at all?

How does the code:

def b_clicked(o):
    return gr.Button.update(interactive=True)

know, which button it is updating? Is this implied by outputs = o?
How would this work if I wanted to update several components at once, say, if we had β€œOther Button 1” and β€œOther button 2” there?

Kind regards,
Jin

1 Like

Hi Jin,

You can define both output and inpus as lists.
E.g. you define output as the list of 2 parameters ([o,oo]. In the return of the function (b_clicked) you send back 2 arguments, the 1st argument correspondents to the 1st element of the output list (o), the 2nd argument correspondents to the 2nd element of the output list (oo)

import gradio as gr                                                             

def b_clicked(b):
    return gr.Button.update(interactive=True), gr.Button.update(interactive=True)
    

with gr.Blocks() as app:
    b = gr.Button("Enable the other obutton", interactive = True)
    o = gr.Button("Other Button1", interactive = False)
    oo = gr.Button("Other Button2", interactive = False)
    b.click(fn = b_clicked, inputs = b, outputs = [o,oo])

if __name__ == "__main__":
    app.launch()
3 Likes

Aaah, now I get it, thank you for the explanation, @Bigiman ! That was the missing link for me, the outputs list which is the callback function parameter corresponds to the return values of the callback function, now it’s clear.

2 Likes