Skip to main content
Events are the mechanism that makes Gradio applications interactive. An event listener connects a component interaction (like a button click) to a Python function, allowing you to respond to user actions in real-time.

What are events?

In Gradio, events are triggered by user interactions with components. When an event occurs, Gradio can:
  1. Run a Python function
  2. Pass component values as inputs to that function
  3. Update other components with the function’s outputs
This creates the interactive loop that powers Gradio applications.

Basic event structure

Every event listener follows this pattern:
component.event_name(
    fn=function_to_run,
    inputs=[input_components],
    outputs=[output_components]
)
For example:
import gradio as gr

def greet(name):
    return f"Hello, {name}!"

with gr.Blocks() as demo:
    name_input = gr.Textbox(label="Name")
    output = gr.Textbox(label="Greeting")
    button = gr.Button("Greet")
    
    button.click(fn=greet, inputs=name_input, outputs=output)

Common event types

Click events

Triggered when a button is clicked:
import gradio as gr

def process():
    return "Button clicked!"

with gr.Blocks() as demo:
    output = gr.Textbox()
    button = gr.Button("Click me")
    
    button.click(fn=process, inputs=None, outputs=output)

Change events

Triggered when a component’s value changes:
import gradio as gr

def update(text):
    return text.upper()

with gr.Blocks() as demo:
    inp = gr.Textbox(label="Type here")
    out = gr.Textbox(label="Uppercase")
    
    inp.change(fn=update, inputs=inp, outputs=out)
The .change() event fires both when users type AND when the value is updated programmatically. Use .input() for events triggered only by user input.

Submit events

Triggered when users press Enter in a textbox:
import gradio as gr

def process(text):
    return f"You submitted: {text}"

with gr.Blocks() as demo:
    inp = gr.Textbox(label="Press Enter to submit")
    out = gr.Textbox()
    
    inp.submit(fn=process, inputs=inp, outputs=out)

Input events

Triggered only by direct user input (not programmatic updates):
import gradio as gr

def count_chars(text):
    return f"Character count: {len(text)}"

with gr.Blocks() as demo:
    inp = gr.Textbox(label="Type here")
    out = gr.Textbox(label="Count")
    
    inp.input(fn=count_chars, inputs=inp, outputs=out)

Select events

Triggered when selecting items in components like Gallery, Dataframe, or highlighted text:
import gradio as gr

def show_selection(evt: gr.SelectData):
    return f"You selected: {evt.value} at index {evt.index}"

with gr.Blocks() as demo:
    gallery = gr.Gallery([("cat.jpg", "Cat"), ("dog.jpg", "Dog")])
    output = gr.Textbox()
    
    gallery.select(fn=show_selection, inputs=None, outputs=output)

Event data objects

Some events provide additional context through event data classes:

SelectData

Contains information about selected items:
import gradio as gr

def on_select(evt: gr.SelectData):
    return f"Index: {evt.index}, Value: {evt.value}"

with gr.Blocks() as demo:
    dataframe = gr.Dataframe([[1, 2], [3, 4]])
    output = gr.Textbox()
    
    dataframe.select(fn=on_select, inputs=None, outputs=output)
SelectData attributes:
  • evt.index - Index of selected item (or tuple for 2D components)
  • evt.value - Value of selected item
  • evt.selected - True if selected, False if deselected
  • evt.target - The component that triggered the event

LikeData

For chatbot like/dislike events:
import gradio as gr

def handle_like(evt: gr.LikeData):
    action = "liked" if evt.liked else "disliked"
    return f"You {action} message {evt.index}: {evt.value}"

with gr.Blocks() as demo:
    chatbot = gr.Chatbot([["Hello", "Hi there!"]])
    output = gr.Textbox()
    
    chatbot.like(fn=handle_like, inputs=None, outputs=output)
LikeData attributes:
  • evt.index - Index of the liked/disliked message
  • evt.value - Content of the message
  • evt.liked - True if liked, False if disliked

KeyUpData

For key press events:
import gradio as gr

def on_key(evt: gr.KeyUpData):
    return f"Key: {evt.key}, Input: {evt.input_value}"

with gr.Blocks() as demo:
    dropdown = gr.Dropdown(["a", "b", "c"], allow_custom_value=True)
    output = gr.JSON()
    
    dropdown.key_up(fn=on_key, inputs=None, outputs=output)

Event chaining

Chain events together using .then(), .success(), and .failure():

Sequential execution with .then()

import gradio as gr

def step1(text):
    return text.upper()

def step2(text):
    return text + "!!!"

with gr.Blocks() as demo:
    inp = gr.Textbox()
    mid = gr.Textbox()
    out = gr.Textbox()
    btn = gr.Button("Process")
    
    btn.click(fn=step1, inputs=inp, outputs=mid).then(
        fn=step2, inputs=mid, outputs=out
    )

Success and failure handlers

import gradio as gr

def risky_operation(x):
    if x < 0:
        raise ValueError("Negative numbers not allowed!")
    return x * 2

def on_success():
    return "Operation completed successfully!"

def on_failure():
    return "Operation failed!"

with gr.Blocks() as demo:
    inp = gr.Number()
    out = gr.Number()
    status = gr.Textbox()
    btn = gr.Button("Calculate")
    
    btn.click(
        fn=risky_operation, inputs=inp, outputs=out
    ).success(
        fn=on_success, inputs=None, outputs=status
    ).failure(
        fn=on_failure, inputs=None, outputs=status
    )

The gr.on() function

Use gr.on() to trigger a function from multiple events:
import gradio as gr

def process(text):
    return text.upper()

with gr.Blocks() as demo:
    textbox = gr.Textbox()
    button = gr.Button("Submit")
    output = gr.Textbox()
    
    # Same function triggered by both events
    gr.on(
        triggers=[button.click, textbox.submit],
        fn=process,
        inputs=textbox,
        outputs=output
    )
This is more efficient than setting up separate listeners - it creates only one API endpoint.

Event parameters

Controlling behavior

button.click(
    fn=process,
    inputs=inp,
    outputs=out,
    # Control queueing
    queue=True,  # Use the queue (default)
    concurrency_limit=3,  # Max 3 simultaneous executions
    
    # Control trigger behavior
    trigger_mode="once",  # "once", "multiple", or "always_last"
    
    # Display options
    show_progress="full",  # "full", "minimal", or "hidden"
    scroll_to_output=True,  # Auto-scroll to output
    
    # API options
    api_name="process_text",  # Custom endpoint name
    api_visibility="public"  # "public", "private", or "undocumented"
)

Trigger modes

  • “once” (default): Prevents new submissions while one is running
  • “multiple”: Allows unlimited simultaneous submissions
  • “always_last”: Queues the most recent submission, cancelling intermediate ones
import gradio as gr
import time

def slow_process(x):
    time.sleep(3)
    return x * 2

with gr.Blocks() as demo:
    inp = gr.Number()
    out = gr.Number()
    btn = gr.Button("Process")
    
    btn.click(
        fn=slow_process,
        inputs=inp,
        outputs=out,
        trigger_mode="always_last"  # Always process the latest value
    )

Cancelling events

Cancel running events when a new event starts:
import gradio as gr
import time

def long_process(x):
    for i in range(10):
        time.sleep(1)
        yield f"Step {i}: {x}"

with gr.Blocks() as demo:
    inp = gr.Textbox()
    out = gr.Textbox()
    start_btn = gr.Button("Start")
    stop_btn = gr.Button("Stop")
    
    click_event = start_btn.click(fn=long_process, inputs=inp, outputs=out)
    
    # Clicking stop cancels the running event
    stop_btn.click(fn=None, inputs=None, outputs=None, cancels=[click_event])

Preprocessing and postprocessing

Control how data flows through events:
button.click(
    fn=process,
    inputs=image,
    outputs=result,
    preprocess=True,   # Convert image to expected format before fn
    postprocess=True   # Convert fn output for display
)
Set to False to work with raw component data:
# Get base64 image string instead of PIL Image
button.click(
    fn=process_base64,
    inputs=image,
    outputs=result,
    preprocess=False  # Skip conversion to PIL
)

Generator functions

Use generator functions for streaming outputs:
import gradio as gr
import time

def stream_data(text):
    for word in text.split():
        time.sleep(0.5)
        yield word

with gr.Blocks() as demo:
    inp = gr.Textbox()
    out = gr.Textbox()
    btn = gr.Button("Stream")
    
    btn.click(fn=stream_data, inputs=inp, outputs=out)
Outputs update in real-time as the generator yields values.

JavaScript events

Run JavaScript before or after Python functions:
import gradio as gr

with gr.Blocks() as demo:
    inp = gr.Textbox()
    out = gr.Textbox()
    btn = gr.Button("Submit")
    
    btn.click(
        fn=lambda x: x.upper(),
        inputs=inp,
        outputs=out,
        js="() => alert('Processing started!')"
    )

Load events

Run functions when the page loads:
import gradio as gr
import datetime

def get_time():
    return f"Page loaded at {datetime.datetime.now()}"

with gr.Blocks() as demo:
    output = gr.Textbox()
    
    demo.load(fn=get_time, inputs=None, outputs=output)

Component-specific events

Different components support different events:
  • Button: click
  • Textbox: change, input, submit, focus, blur
  • Slider: change, release
  • File: upload, delete, download, change
  • Image: select, change, clear, upload
  • Chatbot: change, select, like, retry, undo, clear
  • Gallery: select, change
  • Dataframe: select, change, input
Check each component’s documentation for its supported events.

Event best practices

Performance: Use gr.on() instead of multiple individual listeners when the same function responds to multiple events.
Responsiveness: Use show_progress="minimal" or "hidden" for fast operations to reduce visual clutter.
State isolation: Remember that State components are session-specific. Different users don’t share state values.
Queueing: Long-running or generator functions require the queue to be enabled (it’s enabled by default).

See also

  • Interface - High-level event handling
  • Blocks - Advanced event patterns
  • Components - Which events each component supports
  • State - Managing persistent data across events