go-app icon indicating copy to clipboard operation
go-app copied to clipboard

Can't update value when share value between parent UI and child UI from both side

Open cxjava opened this issue 2 years ago • 2 comments

I have a page which have the parent app.Compo and child app.Compo. Both input value shared same value: Shared.Name.

The expected behaviour is:

when I change child input value, the parent input value should changed automatically. 2

And when I change parent input value, the child input value also changed automatically too. 3

But child will not changed when I change the parent value.

Here is the test code. Maybe the way I used is not the correct way.

Thank you in advance!

package main

import (
	"log"
	"net/http"

	"github.com/maxence-charriere/go-app/v9/pkg/app"
)

var (
	Shared = &shared{}
)

type shared struct {
	Name string
}

type child struct {
	app.Compo
}

func (c *child) OnMount(ctx app.Context) {
	app.Log(Shared.Name)
}

func (c *child) Render() app.UI {
	return app.Div().Body(
		app.Text("ChildName:"),
		app.Input().Type("text").
			Value(Shared.Name).
			OnChange(c.ValueTo(&Shared.Name)),
	)
}

type parent struct {
	app.Compo
	Name string
}

var _ app.Mounter = (*parent)(nil)

func (c *parent) OnInit() {
	Shared = &shared{
		Name: "will update from child",
	}
}

func (c *parent) OnMount(ctx app.Context) {
	app.Log(Shared.Name)
}

func (c *parent) Render() app.UI {

	return app.Div().Body(
		app.Div().Body(app.Text("ParentName:"),
			app.Input().Type("text").
				Value(Shared.Name).
				OnChange(c.ValueTo(&Shared.Name))),
		app.Div().Style("padding", "5px").Body(&child{}),
	)
}

func main() {
	app.Route("/", &parent{})
	app.RunWhenOnBrowser()
	http.Handle("/", &app.Handler{
		Name:        "Isolate",
		Description: "Isolated functionality test",
	})
	if err := http.ListenAndServe(":8000", nil); err != nil {
		log.Fatal(err)
	}
}

cxjava avatar Mar 08 '23 13:03 cxjava

There will also be no events on the child created when parent changes. There is no magic in go-app. It will just update your parent components, not your child components. If you need to update the child, you need to have to create a reason why it should be updated. That is why there is the state observer construct and If you don't want to use it, you must trigger the update by yourself, like calling update for your children manually.

P.S.: The "OnChange" listens on an event from the DOM and all event Handler will always call "Update" on the component, which will call Render. To limit such updates to cases where they are not needed, I added the "skipUpdate" in one of my PRs last year.

oderwat avatar Mar 08 '23 15:03 oderwat

@oderwat Thank you for your detail explain!

If I want to update my child component, can you give a hint? How can I do that?

cxjava avatar Mar 09 '23 05:03 cxjava

package main

import (
	"log"
	"net/http"

	"github.com/maxence-charriere/go-app/v10/pkg/app"
)

type parent struct {
	app.Compo

	name string
}

func (p *parent) OnMount(ctx app.Context) {
	ctx.Handle("change-parent-name", p.handleChildNameChange)
}

func (p *parent) handleChildNameChange(ctx app.Context, a app.Action) {
	p.name = a.Value.(string)
}

func (p *parent) Render() app.UI {
	return app.Div().Body(
		app.Div().Body(
			app.Text("ParentName:"),
			app.Input().
				Type("text").
				Value(p.name).
				OnChange(p.ValueTo(&p.name))),
		app.Div().
			Style("padding", "5px").
			Body(&child{Name: p.name}),
	)
}

type child struct {
	app.Compo

	Name string
}

func (c *child) Render() app.UI {
	return app.Div().Body(
		app.Text("ChildName:"),
		app.Input().Type("text").
			Value(c.Name).
			OnChange(c.onChange),
	)
}

func (c *child) onChange(ctx app.Context, e app.Event) {
	value := ctx.JSSrc().Get("value")
	ctx.NewActionWithValue("change-parent-name", value)
}

func main() {
	app.Route("/", func() app.Composer { return &parent{} })
	app.RunWhenOnBrowser()
	http.Handle("/", &app.Handler{
		Name:        "Isolate",
		Description: "Isolated functionality test",
	})
	if err := http.ListenAndServe(":8000", nil); err != nil {
		log.Fatal(err)
	}
}

maxence-charriere avatar May 20 '24 09:05 maxence-charriere