Genie Framework implements a low-code API that helps Julia developers quickly and easily create interactive data dashboards and data-centric applications, as well as web-based user interfaces for Julia software. Moreover, it offers a large collection of user interface elements (such as inputs, buttons, sliders, tabs, data tables, responsive layouts, and many more) and powerful plotting capabilities.
To implement a reactive UI, you need to define:
- Interactive UI components
- Reactive variables to hold the component states
- Reactive code to handle interaction
Genie Framework provides a small but complete set of macros in its low-code API with which you can implement all of the above.
The snippet below illustrates the structure of an app with a reactive UI.
module App #setup of the Genie Framework environment using GenieFramework @genietools # reactive code @app begin @in N = 0 @out msg = "" @onchange N begin msg = "N = $N" end end # UI components function ui() [ cell([ p("Enter a number") textfield("N", :N ) ]) cell([ bignumber("The value of N is", :N) ]) ] end # definition of root route @page("/", ui) end
Let's break down this code.
GenieFramework.jl package is comprised of many sub-packages that implement the different blocks in the framework. The include of
GenieFramework.jl exports a select number of sub-packages whose functions are used to build the app. Then, the call to
@app macro delimits the block where reactive code is defined. In it, the
@in variable can be modified from the UI, whereas
@out variables are read only.
Besides the reactive variables, the
@onchange macro defines a block of reactive code that is executed when a reactive variable changes in value. This value change can come from the Julia code or from the front-end code; both will trigger the reactiver code execution.
@outcan only be modified within a block delimited by the
@onchangemacro. Any changes made outside of it will not be reflected in the UI.
There's two ways to implement the UI in Genie Framework: in pure Julia using the low-code API, or in HTML. The example code we're examining showcases the Julia option.
There is an extensive library of UI components that can be instantiated with Julia function calls. These can be divided in two groups:
- Layout: functions that set the page layout by defining rows, cells or columns.
- Components: functions that generate UI components such as input fields, sliders or plots.
The complete list of calls in the API is available in the API/Components section. These functions return the HTML code for the component, which can be inspected by printing their output:
julia> print(cell()) <div class="col col-12 col-sm"></div> julia> print(textfield("N", :N )) <q-input label="N" v-model="N"></q-input>
To define the reactive UI in HTML instead of using Julia calls, you have to write it to a
ui.html file and include it with
@page("/","ui.html"). The code should be comprised of standard HTML constructs, and components from the Quasar framework. For the current example, the UI defined in HTML is:
<div class="col col-12 col-sm"> <h4>Enter a number</h4> <q-input label="N" v-model="N" style="width:200px"></q-input> </div> <div class="col col-12 col-sm"> <st-big-number :number="N" title="The value of N is"></st-big-number> </div>
Finally, you can also call the low-code API from HTML files to add components:
<% textfield("N", :N ) %>
A route is an endpoint address for browsers which, when accessed, will return the page to be rendered. The
@page macro defines a route at the root
/ that will return the page code generated by the
To run the app, first navigate to the directory where the code is and execute
julia --project -i -e 'using Pkg; Pkg.add("GenieFramework")'
Then, launch Julia with
julia --project and run the app:
julia> using GenieFramework julia> Genie.loadapp() # load app julia> up() # start server
While developing, you can make changes to a running app's code. They will they will be automatically loaded and the UI will refresh.