Rendering Reactive{string} in StippleUI page

Hi!
I followed through the basic example of reactive UI in the GenieFramework.

The very simple webapp below is a lineage tracking app of biological samples based on lineage graph. The user writes a sample name and gets back all its parents.

The model.output is initialized as an empty String.
The get_all_parents function returns a Vector of names or an empty String.

When reaching to the model.output directly and passing it to the render_output function I’m getting the expected behavior. Unfortunately to render the whole page I need to pass through the page function that exposes the model values through the synthax: "{{ var }}" or span("", @text(:var)).

When passing that to the render_output I’m getting nothing.

I’ve also tried to bypass that by doing page(model, generate_interface(model)) which didn’t work also.

Just passing the output without the render_output function is printing the array but not as I want it. example: ["name1", "name2"]

To reproduce the example, comment the include("lineage_tracking.jl") and define the default output as output::Union{String, Vector{String}} = ["name1", "name2"], READONLY.

I would appreciate any help with this :pray:.

"""
lineage tracking web app
"""

# packages
using Stipple, StippleUI

include("lineage_tracking.jl")
const graph_file = "lineage_graph.mg"

@vars model_vars begin
    input::String = ""
    output::Union{String, Vector{String}} = "", READONLY
end

function handlers(model)
    on(model.input) do input
        model.output[] = get_all_parents(graph_file, input)
    end

    return model
end

function render_output(output)
    if output != ""
        paragraphs = [p(elm) for elm in output]
    else
        paragraphs = ""
    end
    return paragraphs
end

function generate_interface()
    # result = render_output("{{ output }}")
    result = render_output(span("", @text(:output)))
    ui = row(
        cell(class = "st-module", [
            h1("Lineage Tracking")
            textfield(class = "q-my-md", "Sample name", :input, hint = "Enter Sample name to compute lineage", @on("keyup.enter", "process = true"))

            card(class = "q-my-md", [
                card_section(h2("Result"))
                card_section(result)
            ])
        ])
    )
    return ui
end

route("/") do
    model = model_vars |> init |> handlers
    page(model, generate_interface()) |> html
end

Genie.isrunning(:webserver) || up()

The issue you’re having is that you’re trying to evaluate the output variable in the render_output function when it doesn’t have a value.

The generate_interface function is evaluated once to generate the HTML code for the page. If you check this code by running generate_interface in the REPL, you’ll see that the part generated by card_section(result) is empty. This is because a few lines above you’re passing the string "<span v-text=\"output\"></span>"to render_output, which results in "".

If you want to perform any action on the value of a reactive variable, you need to do so in a handler.

For instance, you could do

@app begin
  @out output = ["one", "two"]
  @in input = ""
  @out rendered_code = ""
  @onchange input begin
      rendered_code = render_output(output)
  end
end

ui() = [p("some components before"), "{{rendered_code}}", p("some components after)]
@page("/", ui)

Note that I’m using a different syntax from your example. This is the new API we introduced some 9 months ago which you can find explained here

Where did you find the example to get started with your app? It’s outdated so I’d like to remove it. If you need more help, you can find us on Discord Genie Community

Hi Pere,

Thank you for your prompt response and assistance. I appreciate your help in troubleshooting the issue I encountered with rendering multi-paragraph output in the GenieFramework.

I’d like to clarify that the example I provided was indeed reactive and functional; however, the challenge arose when attempting to render multi-paragraph output instead of a single string.

I did try the solution you suggested, and it worked similarly with the same problem of rendering. Additionally, I intentionally avoided the macro-overload syntax for the sake of transparency in program logic. I find it easier to follow the code when less is hidden behind the scenes, despite the convenience of a more “low code” solution.

Looking forward to your insights and recommendations.

Best regards,
Ben_Sivan