add docs for SSE

This commit is contained in:
maddalax 2024-10-04 11:12:38 -05:00
parent e235aa58ba
commit 7503e1b2c1
3 changed files with 72 additions and 13 deletions

View file

@ -16,10 +16,7 @@ func ChatRoom(ctx *h.RequestContext) *h.Page {
return h.NewPage(
RootPage(
h.Div(
h.JoinExtensions(
h.TriggerChildren(),
h.HxExtension("ws"),
),
h.TriggerChildren(),
h.Attribute("sse-connect", fmt.Sprintf("/ws/chat/%s", roomId)),
@ -143,10 +140,6 @@ func MessageInput() *h.Element {
return h.Input("text",
h.Id("message-input"),
h.Required(),
h.Class("p-4 rounded-md border border-slate-200 w-full focus:outline-none focus:ring focus:ring-slate-200"),
h.Name("message"),
h.MaxLength(1000),
h.Placeholder("Type a message..."),
h.HxAfterSseMessage(
js.SetValue(""),
),

View file

@ -0,0 +1,65 @@
**Server Sent Events (SSE)**
htmgo supports server-sent events (SSE) out of the box.
This allows you to push data from the server to the client in real-time.
Example of this can be found in the [chat-app](https://github.com/maddalax/htmgo/tree/master/examples/chat) example.
Demo: https://chat-example.htmgo.dev
## How it works ##
1. The client sends a request to the server to establish a connection.
2. The server holds the connection open and sends data (in our case, most likely elements) to the client whenever there is new data to send.
3. The htmgo SSE extension uses https://htmx.org/attributes/hx-swap-oob/ to swap out the elements that the server sends.
**Note**: SSE is **unidirectional** (the server can only send data to the client).
For the client to send data to the server, normal xhr behavior should be used (form submission, triggers, etc).
## Usage
1. Add the SSE connection attribute and the path to the handler that will handle the connection.
```go
h.Attribute("sse-connect", fmt.Sprintf("/chat/%s", roomId))
```
The following **Event Handlers** can be used to react to SSE connections.
```go
h.HxOnSseOpen
h.HxBeforeSseMessage
h.HxAfterSseMessage
h.HxOnSseError
h.HxOnSseClose
h.HxOnSseConnecting
```
**Example:** Adding an event listener handle SSE errors.
```go
h.HxOnSseError(
js.EvalJs(fmt.Sprintf(`
const reason = e.detail.event.data
if(['invalid room', 'no session', 'invalid user'].includes(reason)) {
window.location.href = '/?roomId=%s';
} else if(e.detail.event.code === 1011) {
window.location.reload()
} else if (e.detail.event.code === 1008 || e.detail.event.code === 1006) {
window.location.href = '/?roomId=%s';
} else {
console.error('Connection closed:', e.detail.event)
}
`, roomId, roomId)),
),
```
**Example:** Clearing the input field after sending a message.
```go
func MessageInput() *h.Element {
return h.Input("text",
h.Id("message-input"),
h.Required(),
h.HxAfterSseMessage(
js.SetValue(""),
),
)
}
```

View file

@ -15,10 +15,11 @@ type Example struct {
var examples = []Example{
{
Title: "Chat App Example",
Github: "https://github.com/maddalax/htmgo/tree/master/examples/chat",
Demo: "https://chat-example.htmgo.dev",
Image: "public/chat-example.jpg",
Title: "Chat App Example",
Github: "https://github.com/maddalax/htmgo/tree/master/examples/chat",
Description: "A simple chat application built with htmgo using SSE for real-time updates",
Demo: "https://chat-example.htmgo.dev",
Image: "public/chat-example.jpg",
},
{
Title: "Todo List MVC",
@ -73,7 +74,7 @@ func ExamplesPage(ctx *h.RequestContext) *h.Page {
func ExampleCards() *h.Element {
return h.Div(
h.Class("prose-h2:my-1 prose-img:my-1 grid grid-cols-1 md:grid-cols-3 gap-6 text-center pb-8"), // Using grid for 3-column layout
h.Class("prose-h2:my-1 prose-img:my-1 grid grid-cols-1 md:grid-cols-2 gap-6 text-center pb-8"), // Using grid for 3-column layout
h.List(examples, func(example Example, index int) *h.Element {
return h.Div(
h.Class("border border-gray-200 shadow-sm rounded-md px-4 pb-4 bg-neutral-100"), // Removed specific width, handled by grid