vugu / vugu

Vugu: A modern UI library for Go+WebAssembly (experimental)
https://www.vugu.org
MIT License
4.8k stars 175 forks source link

How to stop re-render from overwriting animated components #197

Open Nv7-GitHub opened 3 years ago

Nv7-GitHub commented 3 years ago

I am trying to use bootstrap modals - https://getbootstrap.com/docs/5.0/components/modal/ When the page re-renders, for example, if a user clicks something in the modal or types in the modal, the modal disappears due to the re-render. Is it possible to get around this?

Nv7-GitHub commented 3 years ago

There are some other examples too, but this is the easiest one to reproduce.

bradleypeabody commented 3 years ago

Not sure off the top of my head. I can comment more if I see a code snippet that demonstrates the issue.

Nv7-GitHub commented 3 years ago

I have this bootstrap modal:

<div class="form-group">
      <label>Note Name</label>
      <vgform:Input type="text" class="form-control" :Value="vgform.StringPtr{&c.Name}" placeholder="Name"></vgform:Input>
      <label>Password (optional)</label>
      <vgform:Input type="text" class="form-control" :Value="vgform.StringPtr{&c.Password}" placeholder="Password"></vgform:Input>
    </div>
    <div class="btn-group mt-3">
    <button class="btn btn-danger" @click='c.ModalShowing = false'><i class="fa fa-arrow-left"></i>&nbsp;Back</button>
      <button class="btn btn-success" @click="go c.NewNote(event.EventEnv())"><i class="fa fa-save"></i>&nbsp;Create</button>
    </div>

When the page re-renders, the modal disappears but leaves the page in a shadow. I found a workaround to this by closing the modal and then reopening it every time the page re-renders, but now, every time the user presses anything, the modal plays the closing & opening animation. Is there a way to prevent the re-render from affecting the modal? I believe the issue is because bootstrap is changing the HTML, but when it re-renders, the changed HTML is not preserved.

bradleypeabody commented 3 years ago

I believe the issue is because bootstrap is changing the HTML, but when it re-renders, the changed HTML is not preserved.

This is definitely possible.

If you know what the change is that boostrap JS is making, possibly you can make those same changes in the HTML yourself. I believe a lot of the functionality you're looking for is available by just changing some of the class attributes on various attributes, which you can easily do directly in Vugu.

Nv7-GitHub commented 3 years ago

I might be able to replicate bootstrap's changes, but I have some more complicated scripts that are causing complicated changes to the DOM which would be difficult to replicate, any idea on how to get around that?

bradleypeabody commented 3 years ago

Unfortunately there is currently not a good solution for this. Vugu expects to be able to control the DOM itself and does not have a way to know that certain DOM changes should be allowed and that the render should not overwrite them. There was some discussion around the idea of having "unmanaged" elements here https://github.com/vugu/vugu/issues/155 , but that has not yet been implemented.

Xumeiquer commented 3 years ago

I am using the same modal from bootstrap 5.0 and it is not re-rendering anything. Well It did, but I solved like this.

This is the html button that fires the modal

<button type="button" class="btn btn-success" 
    style="margin-left: 10px;"
    @click='c.ShowModal()'>Show Modal</button>

This is the Go code to handle the click callback

func (h *Header) ShowModal() {
    fmt.Println("Header ShowModal")

    modalElem := js.Global().Get("document").Call("getElementById", "modalID")
    bootstrap := js.Global().Get("bootstrap").Get("Modal")

    modal := bootstrap.New(modalElem, map[string]interface{}{
        "backdrop": true,
        "keyboard": true,
        "focus": true,
    })

   modal.Call("toggle")

   h.modal = modal // keep track of it so you can dismiss the modal later on
}

Then add another event for each action needed in the modal, like confirm button. From that callback you can dismiss the modal and perform any action. Look.

func (h *Header) CrateWalletButtonClick(event vugu.DOMEvent) {
    // Do whatever thing you need

   // dismiss the modal
   h.modal.Call("toggle")

}

Adjust any code to you use case.

Hope this helps.

owenwaller commented 7 months ago

This an #155 are both post v1.0 I think.