GenieFramework / StipplePlotly.jl

Plotly integration for Stipple.jl
MIT License
24 stars 5 forks source link

Can watch for events on plot behind a tab #48

Open cwiese opened 2 years ago

cwiese commented 2 years ago

Click event, for example, is not being captured when the plot is not visible when the js_mounted hook is ran.

in both cases (when I am using tabs or not) the watch_plots fails because the "plot" id is not found yet when js_mounted runs

I get a consoler error vue.js:634

   [Vue warn]: Error in mounted hook: "TypeError: Cannot read properties of null (reading 'on')"

   TypeError: Cannot read properties of null (reading 'on')
using Revise
using Stipple, StipplePlotly, StippleUI
using PlotlyBase

@reactive! mutable struct Example <: ReactiveModel
     plot::R{Plot} = Plot(rand(100,2))
     plot_click::R{Dict{String, Any}} = Dict{String, Any}()
end

function ui(model::Example)
    page(model, class = "container", 
    row(class = "st-module", [
        plotly(:plot, syncevents = true),
    ]))
end

function handlers(model)
  on(model.isready) do isready
      isready || return
      push!(model)
  end

  on(model.plot_click) do data
      haskey(data, "points") && @info "Selection: $(getindex.(data["points"], "pointIndex"))"
  end

  return model
end

model = init(Example, debounce=0)

route("/") do
    model |> handlers |> ui |> html
end

# The following line will watch all plots that have syncevents enabled
# or that have set syncprefix explicitly.
Stipple.js_mounted(::Example) = watchplots(:Example)
#=
Stipple.js_mounted(::Example) = join([
    watchplot(:plot)
])
]=#

up(8000)
cwiese commented 2 years ago

using StipplePlotly 0.13.0 and the example above I get this issue:

syncplot.js:19

   Uncaught TypeError: Cannot read properties of undefined (reading 'id')
at watchGraphDiv (syncplot.js:19:83)
at syncplot.js:15:36
at Array.forEach (<anonymous>)
at watchPlot (syncplot.js:15:14)
at Array.<anonymous> (syncplot.js:9:62)
at HTMLDocument.<anonymous> (sentinel.min.js:1:275)

function watchGraphDiv(gd, model, prefix) { console.info('Syncing plot of class \'' + gd.className + '\' to ' + model.$el.id + '.' + prefix) gd.on("plotly_selected", function (data) {

hhaensel commented 1 year ago

Not sure where the example is from, but it should be

Stipple.js_mounted(::Example) = watchplots()

If I'm right, that also works for hidden plots. New API would be

using Stipple.ReactiveTools
@mounted Example watchplots()
hhaensel commented 1 year ago

The new API version would be

using Stipple, Stipple.ReactiveTools
using StippleUI
using StipplePlotly
using PlotlyBase

@app begin
    @in plot::R{Plot} = Plot(rand(100,2))
    @in plot_click = Dict{String, Any}()

    @onchange plot_click begin
        haskey(plot_click, "points") && @info "Selection: $(getindex.(plot_click["points"], "pointIndex"))"
    end
end

function ui()
    [ 
        row(class = "st-module", style = "height: 300px", [
            plotly(:plot, syncevents = true),
        ])
    ]
end

@mounted watchplots()

@page("/", ui)

up()