gopherjs-vue icon indicating copy to clipboard operation
gopherjs-vue copied to clipboard

Can't find a elegant way to define a multi instanciated component

Open lpuigo opened this issue 8 years ago • 1 comments

Hi Oskca,

First of all, many thanks for this very nice and convenient GopherJS extension on VueJS.

I'm struggling with proper Component definition in order to define a component wich can be instanciated many time within a html page

I've finally wrote this working code :

const (
	TemplateCounter = `
	<div class="ui labeled button" tabindex="0" @click="Inc">
		<div class="ui button" :class="color">
			<i class="heart icon"></i> Like
		</div>
		<a class="ui basic left pointing label" :class="color">{{cnt}}</a>
	</div>
`
)

// CounterComp GopherJs Code
type CounterComp struct {
	*js.Object
	Cnt int `js:"cnt"`
}

func NewCounterComp() *CounterComp {
	cc := &CounterComp{
		Object: js.Global.Get("Object").New(),
	}
	cc.Cnt = 0
	return cc
}

func (cc *CounterComp) Inc() {
	cc.Cnt++
}


// RegisterCompteurComp registers to current vue intance a counter component having the following profile
//  <counter color="some_color_name"></counter>
func RegisterCompteurComp() *vue.Component {
	o := vue.NewOption()
	o.Template = TemplateCounter

	//o.Data = func() interface{} {
	//	return NewCounterComp()
	//}
	// which is equivalent to following
	//o.Set("data", NewCounterComp)
	// and also equivalent to following (kept because shorter)
	o.Data = NewCounterComp

	o.AddMethod("Inc", func(vm *vue.ViewModel, args []*js.Object) {
		vm.Data.Set("cnt", vm.Data.Get("cnt").Int()+1)
	})

	o.AddProp("color")

	return o.NewComponent().Register("counter")
}

This code works ok (it enables multiple counter component intances to work side to side, with a specific value in each occurence), but It does not please me :

As o.SetDataWithMethods(NewMessageComp) ( nor o.SetDataWithMethods(NewMessageComp())) does not seem to work in this case (method "Inc" is not defined on JS side), is there a way to use the actual method assocatied with the Go type, instead of having to "rewrite" the logic in a (Gopher)JS way ?

As a turn around, I used the o.AddMethod... stuff, but it is frustrating for me as it does not reuse the func (cc *CounterComp) Inc() method from CounterComp Go type.

Any hint (or even better, a more comprehensive exemple for component) would be really appreciated

Best Regards Laurent

lpuigo avatar Sep 24 '17 17:09 lpuigo

Having a second look at GopherJS wiki (https://github.com/gopherjs/gopherjs/wiki/JavaScript-Tips-and-Gotchas#tips), I found out kind of a solution :

Here is the reworked version of func RegisterCounterComp :

// RegisterCounterComp registers to current vue intance a counter component having the following profile
//  <counter color="some_color_name"></counter>
func RegisterCounterComp() *vue.Component {
	o := vue.NewOption()
	o.Template = TemplateCounter
	o.Data = NewCounterComp

	o.AddMethod("Inc", func(vm *vue.ViewModel, args []*js.Object) {
		(&CounterComp{Object:vm.Data}).Inc()
	})

	o.AddProp("color")

	return o.NewComponent().Register("counter")
}

This doesn't map directly the exported method of Go Type CounterComp, but at least it enables to reuse the Inc() method.

lpuigo avatar Sep 30 '17 16:09 lpuigo