Use server side events to stream data onto the application templates. This allows us to create dynamic operations
in the templates to load specific parts without reloading the entire page.
Any page type can be streamed, but the pages that are streamed should be created specifically for that purpose.
Read about more advanced methods to manipulate the streams
For the feature to work we need to load the erp pkg script package. We can use the tools’ helper .Tools.LoadSSE
that will create the required tag with a dynamic source automatically.
Without this package the sse feature will not work.
data-sse-src - the source of the stream attribute, for this we can again use the tools’ helper .Tools.GetSSESrc with
input parameter of the page that we want to stream
Optional parameters/attributes
data-sse-behaviour - the method that is used to handle the stream
load - the default value, stream will end once it responds with full data
replace - stream will constantly run, and it will replace all the contents of the container node with the events data
push - stream will constantly run, and it will push new content at the end of the nodes content
Contents of th steam can be either simple any type the page template is defined for.
Load behaviour
Using the load behaviour we can create a loader type, the data inside the container will be loaded immediately and once the
event returns the data then the stream is automatically closed
<!DOCTYPE html><html><head> {{ .Tools.LoadSSE }}
</head><body><!-- data-sse-behaviour="load" is the default behaviour and can be skipped if load is used --><divid="t1"data-sse-src="{{ .Tools.GetSSESrc "da-sse-data-page"}}"><!-- contents will be removed once data is 'finished' so loader elements can be added here --><divclass="loader"></div></div></body></html>
Replace behaviour
In this behaviour mode the data of the element will always get replaced when new data is being returned in the stream.
The stream will be open until it returns an error or the window is closed.
Useful to propagate notifications or states.
<!DOCTYPE html><html><head> {{ .Tools.LoadSSE }}
</head><body><!-- data-sse-behaviour="replace" is important here to keep the stream open --><divclass="my-notification-container"id="t1"data-sse-src="{{ .Tools.GetSSESrc "da-sse-notifications-page"}}"data-sse-behaviour="replace"></div></body></html>
Push behaviour
Perhaps the least useful behaviour. Data from the stream is added at the end of the nodes content without replacing the
existing data.
The stream will be open until it returns an error or the window is closed.
Possibly useful for cases where the data is some sort of log.
<!DOCTYPE html><html><head> {{ .Tools.LoadSSE }}
</head><body><!-- data-sse-behaviour="push" is important here to keep the stream open --><divclass="my-log-container"id="t1"data-sse-src="{{ .Tools.GetSSESrc "da-sse-log-page"}}"data-sse-behaviour="push"></div></body></html>
Prepend behaviour
Data from the stream is added at the front of the nodes content without replacing the existing data.
The stream will be open until it returns an error or the window is closed.
<!DOCTYPE html><html><head> {{ .Tools.LoadSSE }}
</head><body><!-- data-sse-behaviour="push" is important here to keep the stream open --><divclass="my-log-container"id="t1"data-sse-src="{{ .Tools.GetSSESrc "da-sse-log-page"}}"data-sse-behaviour="prepend"></div></body></html>
Preload behaviours
The following extra behaviours can be used to first load data and then make it wait for the action to load more data.
Useful for cases where we want to render the content right away in its current state, but we do not want it to re-render
all the time.
loadAndReplace
loadAndPush
loadAndPrepend
Multiple loaders
A page can define multiple loaders, but it’s limited to 6 streams per browser (total of all tabs).
<!DOCTYPE html><html><head> {{ .Tools.LoadSSE }}
<linkrel="stylesheet"href="{{ .Tools.StaticLink "da-sse-styles-css"}}"></head><body><divclass="column full mt-2"><divclass="row"><spanclass="alert"id="notifications"data-sse-src="{{ .Tools.GetSSESrc "da-sse-notifications-page"}}"data-sse-behaviour="replace"></span></div><divclass="column full justify-center mt-2"id="t1"data-sse-src="{{ .Tools.GetSSESrc "da-sse-data-page"}}"><divclass="row justify-center"><divclass="column"><divclass="loader"></div><pclass="text-center">Loading</p></div></div></div></div></body></html>
Subsections of Server side events
Actions and custom data
From version 1.241+
Normally the SSE feature will continue to stream new data, this streams the same contents in a loop, and in most cases is not needed.
To improve this we can use special custom actions on streams to only flush data when there is an
actual change.
Define the custom action to the SSE block
To make the server side events flush data based on actions we need to add the action name to the sse stream.
The name (my-action) is custom that you can define yourself.
With this the data is hidden from the html code. Suitable for actions that contain data that we do
not want the end user to see or edit.
We still use a form but what is being sent is hidden.
<formmethod="post"><inputtype="hidden"name="Send"id="send"value="1"><buttontype="submit"class="form-button">Trigger action</button></form> {{ if .Data.Parameters.Send }}
{{ .Tools.StreamActionEvent "my-action" }}
{{ end }}
Passing data with the action
We can also pass data with the action trigger. We can then read the data on the possible streamed page and change the
rendered content based on the input.
The data should be in json format but the structure is custom.
With forms
With the regular forms data manipulation is limited.
Also note that everything sent like this will be visible in the html code and can be adjusted by the user.
We can read the data that is being passed with the actions and use it to change the data that we render.
We assume the data is:
{"name":"Some user","content":"some text"}
The get method here is the same as elsewhere with dynamics.
<h4> {{ .Data.Stream.Get "name" }} </h4><p><!-- Render server time when content is 'clock' and the content itself when not -->{{ if eq (.Data.Stream.Get "content").String "clock" }}
{{ dtCurrent }}
{{ else }}
{{ .Data.Stream.Get "content" }}
{{ end }}