Adding a Button

All App UI must be contained within a top-level <app> element. Dashborg provides a default CSS stylesheet and a library of custom elements based off the great Semantic UI / Fomantic UI library. These elements are imported by adding ui="dashborg" to the <app> element (See UI Modes). The elements have a “d-” prefix to distinguish them from the standard HTML elements. The first of those is <d-button>. Let’s add a <d-button> to our app. Create a new file called “demo.html” with our new app’s HTML:

1
2
3
4
<app ui="dashborg">
  <h1>Hello World</h1>
  <d-button handler="/@app:run-handler">Run</d-button>
</app>

You are not required to use any of the Dashborg UI controls. If you’re a CSS/HTML expert, Dashborg will render (almost) any HTML. Dashborg UI events are built into the standard HTML tags using “onclickhandler”, “onchangehandler”, etc. Here’s an example of using a standard <a> tag to run our action:

<a onclickhandler="/@app:run-handler" style="font-weight: bold;">Run</a>

If you re-run your program, you should see your “Run” button.

Connected Apps and Handlers

A button that doesn’t do anything when clicked isn’t very useful. In order to respond to UI events (like button clicks, form submissions, etc.) we’ll need to create a connected app. We’ll add our handler to our app’s runtime and then call WriteAndConnectApp() (instead of WriteApp()). We’ll also need our program to continue running while it waits for UI events so we call WaitForShutdown():

 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
package main

import (
    "fmt"

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

func RunHandler() (interface{}, error) {
    fmt.Printf("Running handler!\n")
    return map[string]interface{}{"success": true, "message": "ran handler!"}, 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.WatchHtmlFile("./demo.html", nil)
    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()
}

Now re-run your program. If you click on the button you should see “running handler!” appear on your console.

Handlers can optionally return data and/or errors (exceptions/panics are also caught). Errors are shown in the Dashborg Chrome. So what about the return values? All data is transmitted via JSON between the backend and frontend. Let’s assign the value to the frontend data-model and display it using a d-dataview.

1
2
3
4
5
<app ui="dashborg">
  <h1>Hello World</h1>
  <d-button handler="$.output = /@app:run-handler">Run</d-button>
  <d-dataview bind="$.output"/>
</app>

Refresh your app, click the button, and you’ll see our handler’s output. This is already very powerful. In only a couple of lines of code and a couple minutes, we’ve defined and deployed a fully functional web-app that can trigger backend code. You can of course put anything you want in that handler function – running a process/script, executing some DB cleanup or maintenance, sending an email, etc.

Next - Data Model