gradio-app / gradio

Build and share delightful machine learning apps, all in Python. 🌟 Star to support our work!
http://www.gradio.app
Apache License 2.0
33.42k stars 2.53k forks source link

A custom component that wraps over the JS confirmation box #3324

Closed lvelvee closed 8 months ago

lvelvee commented 1 year ago

The message box support is missing, interactive experience could be improved if we can implement this.

like this

iShot2023-02-26 19 43 00

4108-1

abidlabs commented 1 year ago

Hi @lvelvee you can achieve this using javascript handlers. Here's a quick example:

import gradio as gr

js = "(x) => confirm('Press a button!')"

with gr.Blocks() as demo:
    btn = gr.Button()
    checkbox = gr.Checkbox()

    btn.click(None, None, checkbox, _js=js)

demo.launch()
oobabooga commented 1 year ago

@abidlabs instead of passing the result of confirm() to an element (in your example, a checkbox), is it possible to cancel the call to fn based on the result of confirm()?

I have a button in my UI that calls a Python function that deletes files:

clear_history = gr.Button('Clear history')
clear_history.click(chat.clear_chat_log, None, None)

Users are asking for confirmation popup before the function is actually executed.

lvelvee commented 1 year ago

@abidlabs I agree with you, but can we expose some API for built-in dialog?

abidlabs commented 1 year ago

Interesting, @oobabooga @lvelvee. Exposing an API for the built-in dialog seems a bit niche to me. Could maybe be a custom component (when we support those down the line), so I'll reopen this issue and tag it as such.

In the meantime, you could try something like this to get a similar effect:

import gradio as gr

with gr.Blocks() as demo:
    with gr.Row():
        delete_btn = gr.Button("Delete")
        confirm_btn = gr.Button("Confirm delete", variant="stop", visible=False)
        cancel_btn = gr.Button("Cancel", visible=False)

        delete_btn.click(lambda :[gr.update(visible=False), gr.update(visible=True), gr.update(visible=True)], None, [delete_btn, confirm_btn, cancel_btn])
        cancel_btn.click(lambda :[gr.update(visible=True), gr.update(visible=False), gr.update(visible=False)], None, [delete_btn, confirm_btn, cancel_btn])

demo.launch()

Recording 2023-02-27 at 06 06 16

lvelvee commented 1 year ago

The workaround works, thanks @abidlabs!

oobabooga commented 1 year ago

Brilliant @abidlabs, that worked like a charm for me too.

da03 commented 1 year ago

For those interested in implementing a pop-up confirmation box, I've come up with a workaround based on @abidlabs's solution. The main idea is to utilize the change event listener to monitor if a hidden checkbox has been altered, and resetting the hidden checkbox to ensure that it works multiple times.

Here's the code snippet:

import gradio as gr

js = "(x) => confirm('Are you sure?')"

with gr.Blocks() as demo:
    btn = gr.Button()
    hidden_checkbox = gr.Checkbox(visible=False)
    textbox = gr.Textbox()
    num = gr.Number(visible=False)

    def hidden_checkbox_fn(checkbox_state, number):
        if checkbox_state:
            number += 1
        display = f'confirmed {number} times'
        return False, display, number

    btn.click(None, None, hidden_checkbox, _js=js)
    hidden_checkbox.change(hidden_checkbox_fn, [hidden_checkbox, num], [hidden_checkbox, textbox, num])

demo.launch()

This approach allows you to achieve the desired pop-up confirmation box functionality using existing gradio functions.

A demo of how this works can be found at https://huggingface.co/spaces/yuntian-deng/Gradio-Popup-Confirmation-Demo

oobabooga commented 1 year ago

@da03 this only works the first time. Also, after the first time, it calls the function if you click on "Cancel"

da03 commented 1 year ago

@da03 this only works the first time. Also, after the first time, it calls the function if you click on "Cancel"

Good point! I have changed it to work multiple times now, by resetting the state of the checkbox after calling the function.

abidlabs commented 11 months ago

Hey! We've now made it possible for Gradio users to create their own custom components -- meaning that you can write some Python and JavaScript (Svelte), and publish it as a Gradio component. You can use it in your own Gradio apps, or share it so that anyone can use it in their Gradio apps. Here are some examples of custom Gradio components:

You can see the source code for those components by clicking the "Files" icon and then clicking "src". The complete source code for the backend and frontend is visible. In particular, its very fast if you want to build off an existing component. We've put together a Guide: https://www.gradio.app/guides/five-minute-guide, and we're happy to help. Hopefully this will help address this issue.

abidlabs commented 8 months ago

I'll go ahead and close this issue as its not likely we'll add this as a core component. However, if anyone wants to take a stab at creating a custom component, here is a similar custom Modal component with source code available: https://huggingface.co/spaces/aliabid94/gradio_modal