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() } }