oskca / gopherjs-vue

VueJS bindings for gopherjs
MIT License
149 stars 17 forks source link

Can't find data variable when using vue.NewOption to create component #9

Closed beatscode closed 7 years ago

beatscode commented 7 years ago

I'm not able to use CurrentRoute property in the view. I get ReferenceError: Can't find variable: currentRoute in the console onload. When running vue.NewComponent... I can gain access to the data property in the view. But I need to implement a render method for the component so I needed to use the NewOption api.

Is there something I'm doing wrong?

package main

import (
    "github.com/gopherjs/gopherjs/js"
    "github.com/oskca/gopherjs-vue"
)

type MainComponent struct {
    *js.Object
    CurrentRoute string `js:"currentRoute"`
}

func (c *MainComponent) ViewComponent() {
    println("Hello From ViewComponent")
}

func (c *MainComponent) ChangeRoute() {
    println("Just Changed Route")
}

type VLink struct {
    *js.Object
    Href     string `js:"href"`
    Required string `js:"required"`
}

func (v *VLink) Got(event *js.Object) {
    href := event.Get("target").Get("href")
    println("Going to", href, v)
    event.Call("preventDefault")
    vm := vue.GetVM(v)
    //Console error
    //Error: GetVM: Vue not registerd yet
    println("VM", vm)
}
func InitMainComponent() {
    m := &MainComponent{
        Object: js.Global.Get("Object").New(),
    }
    m.CurrentRoute = "/"
    o := vue.NewOption()
    o.SetDataWithMethods(m)
    //o.AddProp("currentRoute")
    //o.Set("currentRoute", "/")
    // o.SetRender(func(vm *vue.ViewModel, fn vue.CreateElement) {

    // })
    o.Template = MainTemplate
    o.NewComponent().Register("main-layout")
}
func InitVlinkComponent() {
    v := &VLink{
        Object: js.Global.Get("Object").New(),
    }
    o := vue.NewOption()
    o.SetDataWithMethods(v)
    o.AddMethod("Go", func(vm *vue.ViewModel, args []*js.Object) {
        event := args[0]
        href := event.Get("target").Get("href")
        event.Call("preventDefault")
        println("Going", href)
        vm.Emit("changeRoute")
    })
    o.AddComputed("isActive", func(vm *vue.ViewModel) interface{} {
        i := vm.Data.Get("isActive").Bool()
        return i
    })

    o.AddProp("href")
    o.Template = VLinkTemplate
    o.NewComponent().Register("v-link")
}

type controller struct {
    *js.Object
}

func main() {
    InitVlinkComponent()
    InitMainComponent()
    //vue.NewComponent(Mainlayout, MainTemplate).Register("main-layout")

    vm := vue.New("#app", new(controller))

    js.Global.Set("vm", vm)
    println("vm:", vm)
}

const (
    MainTemplate = `
   <div class="container">
    Current Route is: <input type=text v-model="currentRoute" />
    <ul>
      <li>
        <v-link href="/" v-on:changeRoute="ChangeRoute">Home</v-link>
        </li>
        <li>
        <v-link href="/about" v-on:changeRoute="ChangeRoute">About</v-link>
      </li>
    </ul>

    <slot></slot>
  </div>
`

    VLinkTemplate = `
      <a 
    v-bind:href="href"
    v-bind:class="{ active: isActive }"
    v-on:click="Go"
  >
    <slot></slot>
  </a>
    `
)
beatscode commented 7 years ago

Still trying to understand but components seemed to render when I set the option.Data as a function. Seems like o.SetDataWithMethods and o.Data were clashing overwrote the data object.

func InitMainComponent() {
    m := &MainComponent{
        Object: js.Global.Get("Object").New(),
    }
    o := vue.NewOption()
    o.SetDataWithMethods(m)
    o.Data = func() interface{} {
        data := make(map[string]interface{})
        data["currentRoute"] = "/"
        return data
    }
    fmt.Println("Data", o.Data)

    o.AddMethod("ChangeRoute", func(vm *vue.ViewModel, args []*js.Object) {
        currentRoute := args[0]
        vm.Data.Set("currentRoute", currentRoute)
    })
    fmt.Println("Data", o.Data)
    // o.SetRender(func(vm *vue.ViewModel, fn vue.CreateElement) {

    // })
    o.Template = MainTemplate
    o.NewComponent().Register("main-layout")
}