jfyne / live

Live views and components for golang
https://discord.gg/TuMNaXJMUG
MIT License
655 stars 27 forks source link

Details is always closed whenever the DOM is patched #38

Closed onionjake closed 2 years ago

onionjake commented 2 years ago

This is using v0.12.1 on Firefox.

The details element will always revert to being closed whenever the DOM is patched. Try by opening the 'Advanced' details section, then pressing the Inside or Outside buttons. I added the Nothing button to show that it is only when things are modified (and not just the triggering of a live event).

Here is the source code used:

package main

import (
    "bytes"
    "context"
    "io"
    "log"
    "net/http"
    "sync"
    "text/template"

    "github.com/jfyne/live"
)

type State struct {
    Inside  int
    Outside int
}

func main() {
    var mu sync.Mutex
    var inside, outside int
    h, err := live.NewHandler(live.NewCookieStore("session-name", []byte("weak-secret")))
    if err != nil {
        log.Fatal("could not create handler")
    }
    h.Render = func(ctx context.Context, data interface{}) (io.Reader, error) {
        tmpl, err := template.New("thermo").Parse(`

Hello<br/>
Outside is: {{.Outside}}
<button live-click="inside">Inside</button>
<button live-click="outside">Outside</button>
<button live-click="nothing">Nothing</button>
<details>
<summary>Advanced</summary>
Inside is: {{.Inside}}
<button live-click="inside">Inside</button>
<button live-click="outside">Outside</button>
<button live-click="nothing">Nothing</button>
</details>
<script src="/live.js"></script>
    `)
        if err != nil {
            return nil, err
        }
        var buf bytes.Buffer
        if err := tmpl.Execute(&buf, data); err != nil {
            return nil, err
        }
        return &buf, nil
    }
    h.HandleEvent("inside", func(context.Context, *live.Socket, live.Params) (interface{}, error) {
        mu.Lock()
        defer mu.Unlock()
        inside += 1

        return &State{inside, outside}, nil
    })
    h.HandleEvent("outside", func(context.Context, *live.Socket, live.Params) (interface{}, error) {
        mu.Lock()
        defer mu.Unlock()
        outside += 1

        return &State{inside, outside}, nil
    })
    h.HandleEvent("nothing", func(context.Context, *live.Socket, live.Params) (interface{}, error) {
        mu.Lock()
        defer mu.Unlock()
        return &State{inside, outside}, nil
    })

    http.Handle("/", h)
    http.Handle("/live.js", live.Javascript{})
    http.ListenAndServe(":8080", nil)
}
jfyne commented 2 years ago

If this is the same code as #37 wrapping the Outside and inside with a span will prevent the body from being patched which I believe is what is closing the details tag.

onionjake commented 2 years ago

Adding the span does the trick. Perhaps there should be a note of some sort in the readme?

If live could detect when it is having to patch a larger element and issue a warning that would be helpful too.