Makie cascading menus

Jake
Wed, 01 Apr 2026 00:12:27 +0000
Visualization

I am trying to build some cascading menus in Makie.jl. If we call them menu1, menu2, menu3, then the options in menu2 will depend upon the result of menu1, and likewise the options in menu3 will depend up the selection in menu2. A Minimum, non-working example is given below. When I uncomment line 53 (it has the comment to uncomment) then the example will not error.

I think what i need is a way to prevent Observables from menu1 to automatically affect menu2, until menu2 is called and similarly for menu3. Is this possible? And if so how?

using GLMakie

kpitables = ["kpi_table1", "kpi_table2", "kpi_table3"]
localidsmatrix = [
    ["id1", "id2", "id3"],
    ["id2", "id3", "id4"],
    ["id3", "id4", "id5"]
]

ids = ["id1", "id2", "id3", "id4", "id5"]
id = "default"
kpitableswithid = Observable{Any}(["default"])
kpis = Observable{Any}(["default"])
kpi = Observable{Any}(["default"])

fig = Figure(size = (800, 600))

menu1 = Menu(fig, options = ids) #, default = ids[1])

on(menu1.selection) do s
    id = s
    # println("Selected ID: $id")
    # find the tables with id
    tmp = String[]
    for (i, kpitable) in enumerate(kpitables)
        # @show (i, kpitable)
        localids = localidsmatrix[i]
        # println("Working on table: $kpitable with ID: $id and localids: $localids")
        if !isempty(localids) && in(id, localids)
            # println(kpitable)
            push!(tmp, kpitable)
        end
    end
    # @show tmp
    kpitableswithid[] = length(tmp) == 0 ? ["No tables with this ID"] : tmp
end

menu2 = Menu(fig, options = kpitableswithid)

# kpitable = Observable{Any}("default")
kpitable = "default"
kpismatrix = [
    ["kpi1", "kpi2", "kpi3", "kpi4", "kpi5", "kpi6", "kpi7", "kpi8", "kpi9", "kpi10"],
    ["kpi11", "kpi12", "kpi13", "kpi14", "kpi15", "kpi16", "kpi17", "kpi18", "kpi19", "kpi20"],
    ["kpi21", "kpi22", "kpi23", "kpi24", "kpi25", "kpi26", "kpi27", "kpi28", "kpi29", "kpi30"]
]

on(menu2.selection) do s
    kpitable = s
    # println("menu2 selection is: $kpitable")
    element = findfirst(x -> x == kpitable, kpitableswithid[])
    @show(element)
    # element = rand(1:3, 1) |> only   # when I uncomment this line there is no error
    kpis[] = kpismatrix[element]  # actual selection will be deterministic
end

menu3 = Menu(fig, options = kpis)

on(menu3.selection) do s
    kpi[] = s
    # @show(id, kpitableswithid[], kpi)
end

fig[1,1] = vgrid!(
    Label(fig, "Select Point ID", width = nothing), menu1,
    Label(fig, "Select KPI Table", width = nothing), menu2,
    Label(fig, "Select KPI", width = nothing), menu3;
    tellheight = false, width = 150
)

ax = Axis(fig[1, 2])

on(kpi) do kpi
    println("Items selected:", kpitableswithid, " ", kpitable, " ", kpi)
end

2 posts - 2 participants