Clock
Push DOM changes from the server without any user interaction.
Clock
Push browser DOM changes from the server without the need for a user to interact with the page.
Live Demo
Source
package examples
import (
"context"
"log"
"net/http"
"time"
l "github.com/SamHennessy/hlive"
. "github.com/SamHennessy/hlive/hhtml"
)
// ClockDemo serves a live, interactive instance of the Clock example for the
// "Live Demo" iframe. It needs a custom session disconnect timeout, so it
// builds its own *l.PageServer instead of returning a plain *l.Page.
func ClockDemo() http.Handler {
ps := l.NewPageServer(clockPage)
// Kill the page session 1 second after the tab is closed
ps.Sessions.DisconnectTimeout = time.Second
return ps
}
func clockPage() *l.Page {
page := l.NewPage()
page.DOM().Title().Add("Clock Example")
page.DOM().Head().Add(Link(Rel("stylesheet"), Href("https://cdn.simplecss.org/simple.min.css")))
page.DOM().Body().Add(
Header(
H1("Clock"),
P("The time updates are being push from the server every 10ms"),
),
Main(
Pre(newClock()),
),
)
return page
}
func newClock() *clock {
t := l.NewLockBox("")
return &clock{
// Forced to a Component (rather than the hhtml Code() tag builder)
// because the clock struct embeds *l.Component directly.
Component: l.C("code", "Server: ", t),
timeStr: t,
}
}
type clock struct {
*l.Component
timeStr *l.LockBox[string]
tick *time.Ticker
}
func (c *clock) Mount(ctx context.Context) {
log.Println("DEBU: start tick")
c.tick = time.NewTicker(10 * time.Millisecond)
go func() {
for {
select {
case <-ctx.Done():
log.Println("DEBU: tick loop stop: ctx")
return
case t := <-c.tick.C:
c.timeStr.Set(t.String())
l.RenderComponent(ctx, c)
}
}
}()
}
// Unmount
// Will be called after the page session is deleted
func (c *clock) Unmount(_ context.Context) {
log.Println("DEBU: stop tick")
if c.tick != nil {
c.tick.Stop()
}
}