Genie Discord forum

Author Avatarkk
10/28/2023, 6:38:00 PM

Hi, is there a way to have variables that exist only in the backend of a reactive code (i.e. they are not declared @in nor @out)? For example, I would like to be able to adjust values in a backend data array that is of variable length depending on some inputs set in UI. Then a button would be used to generate a plot based on the current values in data. So data doesn't need to be reactive, just the plot. This would be accessed from a single route (e.g., "/"). My actual use case is more complicated than this an involves using upload to load file contents into a backend data structure, but the simpler case described above covers the same problem. I've tried declaring data to be global inside and outside the @app and nothing works, except for the limited case where data has a fixed length always, then the various @onchange functions can see the same shared array and its updated values.

Author Avatarkk
10/29/2023, 8:05:52 PM

Okay I figured this out using the reactive example @Pere posted recently. Just needed to declare the data array to be global anywhere it is being updated inside the reactive callbacks. Here's the working test case:

@genietools

@app begin
    data = [0.0, 0.0, 0.0]
    @in d = Dict("description" => "hello", "data" => 1)
    @in change_field = false
    @in replace_dict = false
    @onchange d begin
        @show d
        global data[1] += 1.0
        append!(data, 2.0)
        println("@onchange d, data after", data)
    end
    @onbutton change_field begin
        d["data"] += 1
        global data[2] += 1.0
        println("@onchange change_field, data after", data)
    end
    @onbutton replace_dict begin
        d = Dict("description" => d["description"], "data" => d["data"] + 1)
        global data[3] += 1.0
        println("@onbutton replace_dic, data after", data)
    end
end

ui() = [p("{{d.data}}"),
    btn("Frontend +1 to field", @click("d.data += 1")),
    br(),
    btn("backend +1 to field", @click(:change_field)),
    br(), btn("backend replace dict", @click(:replace_dict))]

@page("/", ui)
up()
Author AvatarJazzdude
10/30/2023, 9:11:58 AM

I was under the impression that @private variables were meant for this purpose. Global variables may have issues with data interference between multiple sessions.

Author AvatarPere
10/30/2023, 9:37:09 AM

@Jazzdude is correct. @private variables are added to the list of variables kept for each user, but they are not reactive and are not sent to the browser. You should use them instead of globals to avoid interference between users

Author Avatarkk
10/30/2023, 5:33:37 PM

Great, thank you x2! @private works. I didn't see @private described in the documentation and it doesn't look like it's there other than as an unmentioned part of a code example here: https://learn.genieframework.com/examples/reactive-ui/asynchronous-task

Author AvatarPere
10/31/2023, 5:57:04 PM

you're right @kk . I've updated the docs and mentioned this macro in a few more places