Skip to content

Sending Custom Events across DomNodes

Attila Szabo edited this page Dec 22, 2023 · 1 revision

Specifying Event Listeners

In Aardvark.Media, we don't have explicit notation of DOM Elements, or their IDs, and use the DomNode abstraction instead. We specify Event Listeners as attributes for a speficic DomNodes. For Example:

    div (AttributeMap.ofListCond [
        onlyWhen (condition) (onMouseMove moveHandler)
    ]) [
        text "Hello"
    ]

This attribute adds a listener to the DOM element's onmousemove event which triggers the server function moveHandler only when the value in condition is true, and removes it when its false. The JavaScript function which triggers server functions is called aardvark.processEvent.

How would we trigger events on a different DomNode though? To communicate between DomNodes, we simply use custom events.

Custom Events

We can trigger custom events using aardvark.processEvent like this:

    aardvark.processEvent('__ID__', 'mycustomevent', { content:'testcontent' });

This code calls aardvark.processEvent and emits and event called 'mycustomevent', sending a (JSON-stringified) anonymous object with one field to the server. The special string '__ID__' (two underscores and the letters I D, follwed by another two underscores) gets replaced by the id of the DOM Element that triggered the event. On the server side, all DomNodes can listen to the event using the appropriate attribute, in this example:

onEvent "mycustomevent" [] (List.head >> Pickler.json.UnPickleOfString >> f)

This code unpickles an object from the JSON content inside the message and applies f on it.

Example

In the initial example, we can listen to the window's mouse move event instead of the div's (which works everywhere on the screen instead of just on the div) like this:

onBoot ("window.onmousemove = function(ev){ aardvark.processEvent('__ID__', 'onglobalmousemove', { X: event.clientX, Y: event.clientY  }) };") (
    div (AttributeMap.ofListCond [
        onlyWhen (condition) (onEvent "onglobalmousemove" [] (List.head >> Pickler.json.UnPickleOfString >> moveHandler)
    ]) [
        text "Hello"
    ]
)

Note that the function moveHandler takes a V2i, which has a constructor taking two arguments. This means that FsPickler can automatically unpickle a JavaScript objects with the two fields X and Y into a V2i without any additional boilerplate code.

As another example, call a JavaScript function opening a file open dialog, and return the selected file, like this:

button [
    onEvent "onchoose" [] (fun files -> printfn "%A" files; LoadFiles files)
    clientEvent "onclick" ("aardvark.processEvent('__ID__', 'onchoose', aardvark.dialog.showOpenDialog({properties: ['openFile', 'openDirectory', 'multiSelections']}));") 
] [text "open directory"]