> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/gradio-app/gradio/llms.txt
> Use this file to discover all available pages before exploring further.

# Blocks and event listeners

> Learn how to build custom Gradio applications using the Blocks class and attach event listeners to create interactive data flows.

The `Blocks` class gives you fine-grained control over your Gradio application. Unlike `Interface`, which automatically creates a simple layout, `Blocks` lets you customize the layout, define multiple data flows, and create complex interactions between components.

## Understanding Blocks structure

Here's a simple example that shows the basic structure of a Blocks app:

```python theme={null}
import gradio as gr

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

with gr.Blocks() as demo:
    name = gr.Textbox(label="Name")
    output = gr.Textbox(label="Output")
    greet_btn = gr.Button("Greet")
    greet_btn.click(fn=greet, inputs=name, outputs=output)

demo.launch()
```

Let's break down what's happening:

<Steps>
  <Step title="Create the Blocks context">
    The `with gr.Blocks() as demo:` clause creates a context where you define your app. All components created inside this context are automatically added to the app.
  </Step>

  <Step title="Add components">
    Components like `Textbox` and `Button` are created inside the context. These are the same components used in `Interface`, but here you have full control over their placement and configuration.
  </Step>

  <Step title="Define event listeners">
    The `click()` method attaches an event listener to the button. This defines the data flow: when the button is clicked, the `greet` function runs with `name` as input and updates `output` with the result.
  </Step>
</Steps>

### Using decorator syntax

You can also attach event listeners using decorators. Skip the `fn` argument and assign `inputs` and `outputs` directly:

```python theme={null}
import gradio as gr

with gr.Blocks() as demo:
    name = gr.Textbox(label="Name")
    output = gr.Textbox(label="Output")
    greet_btn = gr.Button("Greet")
    
    @greet_btn.click(inputs=name, outputs=output)
    def greet(name):
        return f"Hello {name}!"

demo.launch()
```

## Event listeners and interactivity

Gradio automatically determines which components should be interactive based on how they're used:

* **Input components**: Any component that serves as an input to an event listener is made interactive
* **Output-only components**: Components that only serve as outputs are non-interactive
* **Override behavior**: You can explicitly control interactivity with the `interactive` parameter

```python theme={null}
# Make an output component interactive
output = gr.Textbox(label="Output", interactive=True)
```

<Note>
  If a component is neither an input nor an output:

  * With a default value: rendered non-interactive (displaying content)
  * Without a default value: rendered interactive

  You can always override this with `interactive=True` or `interactive=False`.
</Note>

## Types of event listeners

Different components support different event listeners. Here's an example using the `change()` event:

```python theme={null}
import gradio as gr

def welcome(name):
    return f"Welcome to Gradio, {name}!"

with gr.Blocks() as demo:
    gr.Markdown("""
    # Hello World!
    Start typing below to see the output.
    """)
    inp = gr.Textbox(placeholder="What is your name?")
    out = gr.Textbox()
    inp.change(welcome, inp, out)

demo.launch()
```

Instead of requiring a button click, this function triggers whenever you type in the textbox. The `change()` event listener fires when the component's value changes.

### Common event listeners

* **`.click()`**: Triggered when a button or clickable component is clicked
* **`.change()`**: Triggered when a component's value changes
* **`.submit()`**: Triggered when Enter is pressed in an input component
* **`.input()`**: Triggered on every keystroke in a text input
* **`.select()`**: Triggered when text or an item is selected
* **`.upload()`**: Triggered when a file is uploaded
* **`.play()`**: Triggered when media playback starts

<Note>
  Check the [component documentation](/components/overview) to see which event listeners are available for each component.
</Note>

## Multiple data flows

Unlike `Interface`, Blocks apps can have multiple data flows connecting various components. Components can serve as both inputs and outputs:

```python theme={null}
import gradio as gr

with gr.Blocks() as demo:
    with gr.Row():
        num1 = gr.Number()
        num2 = gr.Number()
    
    with gr.Row():
        btn1 = gr.Button("Copy →")
        btn2 = gr.Button("← Copy")
    
    btn1.click(lambda x: x, num1, num2)
    btn2.click(lambda x: x, num2, num1)

demo.launch()
```

In this example, `num1` can act as input to `num2`, and vice versa.

## Function inputs: list vs set

When you have multiple input components, you can pass their values to your function in two ways:

### Option 1: List of arguments

```python theme={null}
def add(num1, num2):
    return num1 + num2

add_btn.click(fn=add, inputs=[a, b], outputs=output)
```

The values are passed as separate arguments in the order they appear in the `inputs` list.

### Option 2: Dictionary (using a set)

```python theme={null}
def sub(data):
    return data[a] - data[b]

sub_btn.click(fn=sub, inputs={a, b}, outputs=output)
```

When you pass `inputs` as a set (using curly brackets `{}`), your function receives a single dictionary where keys are the input components and values are their current values.

<Note>
  Option 2 is particularly useful for functions with many input components, as it makes the function signature cleaner and easier to manage.
</Note>

## Function returns: list vs dict

Similarly, you can return values for multiple outputs in two ways:

### Option 1: Return a list

```python theme={null}
with gr.Blocks() as demo:
    food_box = gr.Number(value=10, label="Food Count")
    status_box = gr.Textbox()
    
    def eat(food):
        if food > 0:
            return food - 1, "full"
        else:
            return 0, "hungry"
    
    gr.Button("Eat").click(
        fn=eat,
        inputs=food_box,
        outputs=[food_box, status_box]
    )
```

Return values in the same order as the `outputs` list.

<Warning>
  For a single output component, return the value directly, **not** as a single-item list. Gradio cannot distinguish whether the outer list is part of your return value or a container.
</Warning>

### Option 2: Return a dictionary

```python theme={null}
with gr.Blocks() as demo:
    food_box = gr.Number(value=10, label="Food Count")
    status_box = gr.Textbox()
    
    def eat(food):
        if food > 0:
            return {food_box: food - 1, status_box: "full"}
        else:
            return {status_box: "hungry"}
    
    gr.Button("Eat").click(
        fn=eat,
        inputs=food_box,
        outputs=[food_box, status_box]
    )
```

With dictionary returns, you can:

* Update only specific outputs (notice how we skip `food_box` when food is 0)
* Update outputs in any order
* Conditionally update different sets of outputs

<Note>
  Even with dictionary returns, you must still specify all possible outputs in the event listener's `outputs` parameter.
</Note>

## Updating component configurations

You can update not just a component's value, but also its configuration (like visibility, label, or interactivity):

```python theme={null}
import gradio as gr

def sentence_builder(quantity, animal):
    return f"The {quantity} {animal}s went to the market."

with gr.Blocks() as demo:
    quantity = gr.Slider(
        2, 20, value=4, step=1, 
        label="Quantity", interactive=True
    )
    animal = gr.Textbox(
        label="Animal", placeholder="Enter an animal"
    )
    output = gr.Textbox(label="Output", interactive=False)
    
    def update_visibility(quantity):
        if quantity < 10:
            return gr.Textbox(visible=True, value="")
        return gr.Textbox(visible=False, value="Hidden!")
    
    quantity.change(update_visibility, quantity, animal)
    gr.Button("Submit").click(sentence_builder, [quantity, animal], output)

demo.launch()
```

Return a new component instance with the properties you want to change. Any properties you don't set will preserve their previous values.

## Not changing a component's value

Sometimes you want to leave a component's value unchanged. Use `gr.skip()` for this:

```python theme={null}
import gradio as gr

with gr.Blocks() as demo:
    textbox = gr.Textbox()
    button1 = gr.Button("Clear")
    button2 = gr.Button("Skip")
    
    button1.click(lambda: None, None, textbox)  # Clears the textbox
    button2.click(lambda: gr.skip(), None, textbox)  # Leaves value unchanged

demo.launch()
```

<Note>
  Returning `None` typically resets a component to its empty state, while `gr.skip()` preserves the current value. If you have multiple outputs and want to leave all unchanged, return a single `gr.skip()` instead of a tuple of skips.
</Note>

## Running events consecutively

Use the `.then()` method to run events in sequence:

```python theme={null}
import gradio as gr
import time

def add_message(history, message):
    history.append((message, None))
    return history, ""

def respond(history):
    time.sleep(1)  # Simulate processing
    response = "Computer says: " + history[-1][0].upper()
    history[-1] = (history[-1][0], response)
    return history

with gr.Blocks() as demo:
    chatbot = gr.Chatbot()
    msg = gr.Textbox()
    send = gr.Button("Send")
    
    send.click(add_message, [chatbot, msg], [chatbot, msg]).then(
        respond, chatbot, chatbot
    )

demo.launch()
```

The `.then()` method executes regardless of whether the previous event raised errors.

### Conditional chaining

* **`.success()`**: Only runs if the previous event completed without errors
* **`.failure()`**: Only runs if the previous event raised an error

These are useful for error handling workflows:

```python theme={null}
submit_btn.click(process_data, inputs, outputs).success(
    show_success_message, None, status
).failure(
    show_error_message, None, status
)
```

## Binding multiple triggers to a function

Use `gr.on()` to bind multiple triggers to the same function:

```python theme={null}
import gradio as gr

with gr.Blocks() as demo:
    input_text = gr.Textbox()
    output = gr.Textbox()
    submit = gr.Button("Submit")
    
    # Trigger on both button click and Enter key
    gr.on(
        triggers=[submit.click, input_text.submit],
        fn=lambda x: x.upper(),
        inputs=input_text,
        outputs=output
    )

demo.launch()
```

### Decorator syntax with gr.on

```python theme={null}
@gr.on([submit.click, input_text.submit], inputs=input_text, outputs=output)
def process_text(text):
    return text.upper()
```

### Creating "live" events

Omit the `triggers` parameter to automatically bind to all `change` events of input components:

```python theme={null}
import gradio as gr

with gr.Blocks() as demo:
    first_name = gr.Textbox(label="First Name")
    last_name = gr.Textbox(label="Last Name")
    full_name = gr.Textbox(label="Full Name")
    
    # Automatically triggers when either input changes
    @gr.on(inputs=[first_name, last_name], outputs=full_name)
    def combine_names(first, last):
        return f"{first} {last}"

demo.launch()
```

## Binding component values directly

For simple cases where a component's value should always be a function of other components, use this shorthand:

```python theme={null}
with gr.Blocks() as demo:
    num1 = gr.Number()
    num2 = gr.Number()
    product = gr.Number(lambda a, b: a * b, inputs=[num1, num2])
```

This is equivalent to:

```python theme={null}
with gr.Blocks() as demo:
    num1 = gr.Number()
    num2 = gr.Number()
    product = gr.Number()
    
    gr.on(
        [num1.change, num2.change, demo.load],
        lambda a, b: a * b,
        inputs=[num1, num2],
        outputs=product
    )
```

## Next steps

Now that you understand how to create Blocks and attach event listeners, you can:

* Learn about [controlling layout](/guides/controlling-layout) to arrange your components
* Explore [state management](/guides/state-in-blocks) to build stateful applications
* Discover [dynamic apps](/guides/dynamic-apps) with the render decorator


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.