B4J Library [BANanoReef] Create reactive, state based components & UI

Mashiane

Expert
Licensed User
Ola

BANanoReef

So I took a small break to check this out, out of curiosity. Reef does one thing, renders the UI and only updates the stuff that has changed.

To develop webistes / web apps with BANano, one uses html, css and javascript. Here we go to basics and create a reactive HTML component, a h1 using data-properties.

We will update parts of it using a template and setting its data properties. What we have below is a HTML h1 component that gets updated every 3 seconds to update the name property..

Reproduction

1. We create a reef object.
2. We set the data to it
3. We create a template for our HTML element and pass it the data
4. We render the reef to the body of the page.


BANanoReef.gif


Let's take a loot at the code...

We have defined a process globals reef component.

B4X:
'initialize a reef and set the object to render it to
    reef.Initialize("#body")
    'define the properties for the element, we have greeting and name
    reef.SetData(CreateMap("greeting": "Hello", "name": "world"))
    'define the h1 html element
    reef.SetTemplate($"<h1>#greeting#, #name#!</h1>"$)
    'we render the element to the body
    reef.Render(False)
We want to change the name at each 3 seconds..

We then define a timer..

B4X:
nameCnt = 0
    timer.Initialize("timer1", 3000)
    timer.Enabled = True
When the timer fires, we change the name property and refresh the element.

B4X:
Sub timer1_tick
    nameCnt = nameCnt + 1
    Select Case nameCnt
    Case 1
        reef.Refresh(CreateMap("name":"Mashy"))
    Case 2
        reef.Refresh(CreateMap("name":"Ozzie"))
    Case 3
        reef.Refresh(CreateMap("name":"Orio"))
    Case 4
        reef.Refresh(CreateMap("name":"Ernesto"))
        nameCnt = 0
    End Select
End Sub
 

Mashiane

Expert
Licensed User
In this next example, we create a button named btn1, we give it a blue background and text of white. We also make it to have a width and height of 100px. This is just normal html and css coding. We place it inside a div called buttons1. This replaces everything inside that div.

Button1.gif


1. Lets create 2 divs, 1 to render the greetings in post 1 and another to hold the button.

B4X:
Dim cont1 As UOEHTML
    cont1.Initialize("cont1").SetTag("div")
    'create a div with id buttons1
    Dim buttons1 As UOEHTML
    buttons1.Initialize("buttons1").SetTag("div")
    '
    'get the body of the page, created by banano,
    Dim body As BANanoElement = banano.GetElement("#body")
    'empty the body
    body.empty
    '
    'add cont1 and buttons1 to body
    body.Append(cont1.HTML)
    body.Append(buttons1.html)
B4X:
2. Lets create a button element and add an event to it.

[CODE]'lets create another html5 component and render it to buttons1 container
    Dim btn1 As BANanoReef
    btn1.Initialize("#buttons1")
    btn1.SetTag("button").SetID("btn1").SetLabel("Button 1")
    btn1.SetStyle("background-color","blue").SetStyle("color", "white")
    btn1.SetHeight("100px").SetWidth("100px")
    btn1.Render(False)
    '
    'event
    banano.GetElement("#btn1").HandleEvents("click", Me, "btn1_click")
As the button is an internal reef component (updated reef class to handle these types of definitions), its template will be rendered like this.

B4X:
<button id='btn1' style='background-color:blue; color:white; height:100px; width:100px;' >{label}</button>
This means that we will be able to change the 'text' or {label} portion of the button.

3. Let's trap the click event

B4X:
Sub btn1_click
    banano.Window.Alert("I clicked btn1!")
End Sub
 

Mashiane

Expert
Licensed User
In this next example, we demo how to use a lagoon. A lagoon is used to store data that you can set in a re-active manner.

Hi Universe!

We will create a html element having...

B4X:
<h1  >{greeting}</h1><div id='todos'  ></div>
We will use data from a lagoon to set the greeting by attaching the lagoon to another reef.

1. We create a div (you can use any framework here off course to make-up your components)

B4X:
Dim lst As UOEHTML
    lst.Initialize("listofthings").SetTag("div")
2. We add the div to the body..

B4X:
body.Append(lst.HTML)
3. We create a lagoon just to store data, this does not have a template. Note that we initialize it with Null as it wont render anywhere

B4X:
sourceOfTruth.Initialize(Null).SetLagoon(True)
    sourceOfTruth.SetDataKeyValue("greeting", "Hello, world!")
    sourceOfTruth.SetDataKeyValue("todos", Array("Buy milk", "Bake a birthday cake", "Go apple picking"))
    sourceOfTruth.Render(False)
Here we have used .SetDataKeyValue for the data of the lagoon, still .SetData is appropriate but we wanted to simply this.

4. We create the main Reef that will use the lagoon data to display what we need. This has a template and we attach it to the previous lagoon reef.

B4X:
app.Initialize("#listofthings")
    app.SetTemplate("<h1>{greeting}</h1><div id='todos' ></div>")
    app.SetAttachTo(sourceOfTruth.Reef)
    app.Render(False)
We then attach the sourceOfTruth reef to the app Reef with .SetAttachTo

5. Now, lets reactively update the greeting to show Hi Universe!

B4X:
sourceOfTruth.Refresh(CreateMap("greeting": "Hi, universe"))
Ta!
 

Mashiane

Expert
Licensed User
The last part of this, we render a list as part of the examples provided...

reactive.png


Here is the code

1. We get the data from the source of truth and get the saved to do list
2. We build up the list structure that we need and set this to the template
3. We attach the sourceoftruth and the app reefs.

B4X:
'render the list
    Dim tdm As Map = sourceOfTruth.GetData
    Dim tlist As List = tdm.Get("todos")
    Dim li As StringBuilder
    li.Initialize
    For Each strl As String In tlist
        li.Append("<li>").Append(strl).Append("</li>")
    Next
    todos.Initialize("#todos")
    todos.SetTemplate($"<h2>Todo List</h2><ul>${li.tostring}</ul>"$)
    todos.SetAttachTo(sourceOfTruth.Reef)
    todos.SetAttachTo(app.Reef)
    todos.Render(False)
That's all folks...
 
Top