Overview

hlivekit.PubSub is a topic-based message bus: any number of subscribers register interest in named topics, and a single Publish call fans a message out to every one of them. Install one instance on a page with InstallPubSub and any component that implements PubSubMount(ctx context.Context, pubSub *PubSub) is handed that instance the moment it mounts — no reference to the PubSub needs to be threaded through the component tree by hand.

Because subscribers are only tied to topic names, components that publish and components that subscribe never need a reference to each other. A form's inputs can each validate themselves and publish "input_invalid" without knowing an error-summary component even exists — it just happens to be listening.

The same mechanism scales past a single page: nothing stops a PubSub instance from being shared across every session on the server, so one user's action can push an update to every other connected session's components in real time.

API

  • hlivekit.NewPubSub() *PubSub — create a bus instance.
  • hlivekit.InstallPubSub(pubSub *PubSub) l.Attributer — wire a bus into a page, typically added to page.DOM().HTML().
  • (*PubSub).Publish(topic string, value any) — broadcast value to every subscriber of topic.
  • (*PubSub).Subscribe(sub QueueSubscriber, topics ...string) — register a subscriber for one or more topics.
  • hlivekit.NewSub(fn func(QueueMessage)) SubscribeFunc — wrap a plain function as a QueueSubscriber.
  • A component opts in by implementing PubSubMount(ctx context.Context, pubSub *PubSub) (and, if it also embeds l.Teardowner, cleans itself up automatically when removed from a ComponentList).

Use case

A form where a name input, an email input, and an error-summary component all validate and react independently: each input publishes input_valid/input_invalid as the user types, the error summary subscribes to both and renders a combined list, and the form itself publishes form_validate on submit to make every input re-check itself first. See the full PubSub example.

Code sample

Adapted from the PubSub example:

pubSub := hlivekit.NewPubSub() page := l.NewPage() page.DOM().HTML().Add(hlivekit.InstallPubSub(pubSub)) type errorSummary struct { *l.Component message *l.NodeBox[string] } // PubSubMount is called automatically once this component mounts. func (c *errorSummary) PubSubMount(_ context.Context, pubSub *hlivekit.PubSub) { pubSub.Subscribe(hlivekit.NewSub(func(m hlivekit.QueueMessage) { c.message.Set(m.Value.(string)) }), "input_invalid") } // Elsewhere, an input publishes on the same topic: nameInput.Add(l.On("input", func(ctx context.Context, e l.Event) { if e.Value == "" { pubSub.Publish("input_invalid", "Name is required.") } }))