Building Apps
Handle user events

Handle user events within your app

💡

In this guide, you'll build upon your knowledge of binding expressions and learn how to explicitly handle events originating from browser user input and call functions based on them.

You can handle explicit user actions by using Dynaboard's flexible event handling mechanism. Below you will find an example of how to set up an event based on button press.

There are many events that can be handled (On Mount, On Click, On Hover, etc.), and the events supported vary based on the component you have selected.

Set up the app

Adding a function

Start by dragging out a Input, then creating a Function on the page by clicking on the + on the bottom-left of the Pages panel in the Dynaboard editor. Select from the quick action menu to Run TypeScript on the Client, then enter the following code snippet:

const val = input1.value
return (
  val
    .split(',')                     // split on ,
    .map(v => Number(v.trim()))     // convert to number
    .reduce((sum, v) => sum + v, 0) // calculate sum
)

Nice function you got there. Hit Save Function to let Dynaboard know to commit your changes.

Now, if you enter some comma-separated numbers into the input using the Interact tool, then click Test Function, you'll see that the result is the sum of those numbers you entered. As you can imagine, this is just an example TypeScript function—you can use any valid ECMAScript 2020 syntax here.

💡

This process works for any type of function attached to any resource. We've used the TypeScript Client here for illustrative purposes, but it works just the same no matter what you pick.

Displaying as text

Let's wire up this function's output to a text node. Create a Text and enter into Value: {{ function1.data }}. This will create a reactive binding between the output of function1 (the function we were just editing) and the text, such that whenever function1 runs, the text will display its latest output value. Try it out by navigating back to function1 and clicking Test Function.

Handling button clicks

You'll notice that there is no way to trigger function1 without clicking the Test Function button. Let's say we'd like to add a button to the page that triggers it, and displays it in the text component we just created on the page.

  1. Add a Button to the page from the toolbar
  2. lick on Events at the top of the right-side inspector panel
  3. Find the On Click event and select function1

Switch back to Interact tool, enter some text, and click your new button. You've handled an event!

Running automatically

Functions will by default be run When Called. That means you'll have to wire it up to an event handler for it to run.

You can alternatively configure your function to run Automatically in the right-side inspector panel. Functions of this sort will run whenever properties referenced in their {{ binding expressions }} change, reflecting the same behavior of component properties. You wouldn't need a button to trigger function1.

If you switch your function to run automatically, you'll notice that it still doesn't appear to work. That's because you'll need to access input1.value in a binding expression, like so (notice line 1):

const val = {{ input1.value }}
return (
  val
    .split(',')                     // split on ,
    .map(v => Number(v.trim()))     // convert to number
    .reduce((sum, v) => sum + v, 0) // calculate sum
)

The inside of binding expressions are always evaluated first before the rest of your function code is executed. These binding expressions, like all binding expressions, must return a non-Promise TypeScript value synchronously. If you'd like to perform asynchronous behavior, you can use async/await in the outer TypeScript, but not within the binding expressions themselves.

💡

Use caution when configuring a function to run automatically. Functions which run automatically are fired immediately upon page load, and hence can cause unnecessary strain on your database when they are unused.

Additionally, functions which run automatically can still perform destructive actions, so it's best to stick to safe actions for these (i.e. pure or query-style functions and not commands).

To prevent pounding your database or API with requests, you can configure the limiter for the function to be a throttle, debounce, or disabled in the function's inspector panel.