Data Model

The frontend of every Dashborg app has a JSON-like data model associated with it. It can be accessed with $ (or $data). There are other data roots (See Special Data Roots) for things like application state ($state), or local data within loops (. or $local). Note that this data model is ephemeral and local to the frontend UI.

At the top level each data root is a map, and it can store any hierachical JSON data: maps, arrays, strings, and numbers. At any point you can see the current state of your panel’s data model by clicking the database icon at the top-right of your panel:

Data Icon

The $state root is special, and represents the state of your application. Everything under the $state tree is automatically serialized and sent to your app’s handlers for every request and can be accessed by calling req.BindAppState().

Setting Data

Let’s start by creating an init handler for our application and marking it as required. Each time our application is loaded our init handler will be called and can set any required initial data. If the init handler returns an error the app will not load (useful for checking parameters or pre-conditions).

Every app handler can take a *dash.AppRequest as an optional first argument. Handlers can use the request struct to set data directly into the frontend data model. Here we’ll set $.color to “blue” in our init handler.

We’ll also modify our RunHandler to overwrite the color and change it to “red”.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package main

import (
	"fmt"

	"github.com/sawka/dashborg-go-sdk/pkg/dash"
)

func RunHandler(req *dash.AppRequest) (interface{}, error) {
	fmt.Printf("Running handler!\n")
	req.SetData("$.color", "red")
	return map[string]interface{}{"success": true, "message": "ran handler!"}, nil
}

func InitHandler(req *dash.AppRequest) error {
	req.SetData("$.color", "blue")
	return nil
}

func main() {
	config := &dash.Config{AutoKeygen: true, AnonAcc: true}
	client, err := dash.ConnectClient(config)
	if err != nil {
		fmt.Printf("Error connecting Dashborg client: %v\n", err)
		return
	}
	app := client.AppClient().NewApp("demo")
	app.SetOfflineAccess(true)
	app.SetInitRequired(true)
	app.WatchHtmlFile("./demo.html", nil)
	app.Runtime().SetInitHandler(InitHandler)
	app.Runtime().Handler("run-handler", RunHandler)
	err = client.AppClient().WriteAndConnectApp(app)
	if err != nil {
		fmt.Printf("Error writing app: %v\n", err)
		return
	}
	client.WaitForShutdown()
}
$ always refers to the root of the data-model tree. Use dot . syntax to access keys, and use brackets [0] or [1] to set array indexes. Any data that you pass to SetData / set_data is serialized to JSON, so you can pass maps, structs, slices, etc. to set complex data structures.

Restart your program and refresh the Dashborg page and if you click on the data-model icon you’ll see “blue” set. If you click the “Run” button you’ll see “red”.

Binding Data to Your UI

You can use any data in the data model in your UI. You do that through binding. The simplest element is the <d-text> element which converts data from the model to HTML text.

<d-text> can also be used to format numbers, or more complex text using a printf-like syntax. Dashborg uses the sprintf.js library to format output. You can set a format string using the format attribute on <d-text>. Here’s an example of formatting a floating point number to two decimal places:

<d-text bind="$.num" format="%0.2f"/>

You can also use the data-model to set any attribute value or any style property. Any value that starts with * will be evaluated in the data-model. In a * expression you also have access to functions and simple arithmatic, string, and conditional expressions (expression reference).

We’ll add a 100x100 box to our app’s HTML with its color set to the color from the model.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<app ui="dashborg">
  <h1>Hello World</h1>
  <d-button handler="/run-handler">Run</d-button>
  <div>
    The color is <d-text bind="$.color"/>!
  </div>
  <div style="width: 100px; height: 100px; background-color: *$.color; color: white; fullcenter;">
    <d-text bind="$.color"/>
  </div>
</app>

Refresh the Dashborg panel (no need to restart your program since we only changed demo.html) and you should see the text and a blue box. If you click the “Run” button the box and text should change to red.

Panel With Color Box

The box’s color comes from the background-color: *$.color; property set in the style attribute. By using the *, the background color is pulled from the data-model. If you know CSS you also might have noticed the fullcenter CSS property. That’s a Dashborg Style Extension. Their use is completely optional, but they can be a nice shorthand for doing styling that often requires a lot of typing (like centering text in a box vertically and horizontally).