[Python] Dynamically adding and removing UI elements

Discussão em 'Python' iniciado por Stack, Agosto 11, 2025.

  1. Stack

    Stack Membro Participativo

    I am trying to dynamically add and remove UI elements to a python shiny application. For adding elements I want to have a generic "Add element" button. For removal however, I want to have an individual "X" button at the corner of each element. Adding elements already works as it should. I am currently struggling with observing the clicks on each individual "X" button.

    The code I have currently is this:

    from shiny import App, ui, reactive

    # Define the UI
    app_ui = ui.page_fluid(
    ui.input_action_button("add_square", "Add Square", class_="btn btn-primary"),
    ui.div(id="square_container", class_="container"),
    ui.tags.style(
    """
    .rounded-square {
    width: 120px;
    height: 120px;
    background-color: #f9f9f9; /* Light gray background */
    border-radius: 15%;
    display: flex;
    justify-content: center;
    align-items: center;
    margin: 10px;
    box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
    position: relative;
    }
    .container {
    display: flex;
    flex-wrap: wrap;
    gap: 15px;
    margin-top: 20px;
    justify-content: center;
    }
    .delete-btn {
    position: absolute;
    top: 5px;
    right: 5px;
    background-color: #ff4d4d;
    color: white;
    border: none;
    border-radius: 50%;
    width: 20px;
    height: 20px;
    font-size: 12px;
    cursor: pointer;
    text-align: center;
    line-height: 17px;
    padding: 0;
    }
    .delete-btn:hover {
    background-color: #e60000;
    }
    """
    ),
    )


    # Define the server logic
    def server(input, output, session):
    # Reactive list to store square IDs
    square_ids = reactive.Value([])

    @reactive.Effect
    @reactive.event(input.add_square)
    def add_square():
    """Add a new square dynamically."""
    current_ids = square_ids.get()

    # Generate a new unique ID for the square
    new_id = max(current_ids, default=0) + 1
    current_ids.append(new_id)
    square_ids.set(current_ids)

    # Add a new square dynamically into the DOM
    ui.insert_ui(
    ui=ui.div(
    ui.TagList(
    ui.input_text(
    f"text_{new_id}", None, placeholder=f"Square {new_id}"
    ),
    ui.input_action_button(
    f"delete_{new_id}", "X", class_="delete-btn"
    ),
    ),
    id=f"square_{new_id}", # Unique ID for the square
    class_="rounded-square",
    ),
    selector="#square_container", # Add inside the container
    where="beforeEnd",
    )

    @reactive.effect
    def monitor_delete_buttons():
    """Monitor delete button clicks and handle square deletions."""
    current_ids = square_ids.get()

    for square_id in current_ids:
    # Check if the delete button for `square_id` has been clicked
    if input.get(f"delete_{square_id}", 0) > 0:
    # Remove the square from the UI
    ui.remove_ui(selector=f"#square_{square_id}")

    # Update the reactive square list
    updated_ids = [s for s in current_ids if s != square_id]
    square_ids.set(updated_ids)

    # Reset the delete input to avoid duplicate actions
    session.reset_input(f"delete_{square_id}")
    break


    # Create the Shiny app
    app = App(app_ui, server)

    Continue reading...

Compartilhe esta Página