Edit vector interactively using PlutoUI

Hi,
This is a simplified example of what I need to do:

x = rand(10)
bar(x)
@bind idx Slider(1:length(x))
@bind del Button("-")

I want to trigger deleteat!(x, idx) only when button is pressed and then to refresh the plot and the slider. How to prevent the deleteat! being triggered automatically and only when the button is pressed and how to refresh x later on?

Thanks, Adam

I think we could start chipping away at this by using confirm in PlutoUI. For example, something like:

example1

using Plots, PlutoUI

x = Vector{Union{Float64, Missing}}(rand(5))

@bind idx confirm(Slider(eachindex(x); show_value=true))

begin
    replace!(x, x[idx] => missing)

    bar(x)
    xlims!(0, length(x) + 1)
    ylims!(0, 1)
end

I just made a few tweaks to make it a bit easier for me to see which bars are being removed, but you don’t have to do this. The main difference is that the plot will only update after the confirm button is clicked

As you can see though, this is automatically removing the first bar before we do anything because the default value from the slider is the first index of x. To get around this, I think we could put the deletion behind a CheckBox and then update everything all together with PlutoUI.combine:

example2

@bind options confirm(
    PlutoUI.combine() do Child
        md"""
        Delete idx: $(Child("idx", Slider(eachindex(y))))

        Update graph: $(Child("update", CheckBox()))
        """
    end
)

begin
    options.update && replace!(y, y[options.idx] => missing)

    bar(y)
    xlims!(0, length(y) + 1)
    ylims!(0, 1)
end

I like this approach because it creates a named tuple that we can use to refer to each widget. Interestingly though, trying to add show_value to Slider here seems to break things. I’m not sure if this is intended or a known issue, but maybe the Pluto folks would have some more info about this?

3 Likes

Thanks! The issue is that in your solution the length of x is constant and mine should decrease after each removal. Nevertheless, that somewhat does the trick and will suffice until I find a better solution :slight_smile: