Closed Xumeiquer closed 3 years ago
if c, ok := b.(middleware.APISetter); ok {
Are you sure middleware.APIRef
implements middleware.APISetter
? Please show the definitions of those.
I am quite sure, here is the code for the API and the State.
midlleware/api.go
package middleware
import (
"io/ioutil"
"net/http"
"net/url"
)
type APIRef struct{ *API }
type APISetter interface{ APISet(*API) }
func (cr *APIRef) APISet(c *API) { cr.API = c }
type API struct {
Endpoint string
}
func NewAPI(endpoint string) *API {
return &API{
Endpoint: endpoint,
}
}
[...]
midlleware/state.go
package middleware
import (
"errors"
)
type StateRef struct{ *State }
type StateSetter interface{ StateSet(*State) }
func (cr *StateRef) StateSet(c *State) {
cr.State = c
}
type State struct {
Data map[string]interface{}
}
func NewState() *State {
return &State{
Data: make(map[string]interface{}),
}
}
[...]
As I said I copy and renamed the example from the documentation website.
I see. I would try adding some log statements right inside buildEnv.SetWireFunc(func(b vugu.Builder) {
to look closely at the value of b
. Statements like if c, ok := b.(middleware.APISetter); ok {
are just straight Go, there's no magic that Vugu is doing with them. So either that if statement is not firing because b does not implement the interface, or that line is not getting called. Add log statements until you and find which of those cases is occurring and go from there.
Hi, I've just create a new project from scratch to be able to spot the issue. Well, I didn't find the issue, but Vugu does its job really well so there is no issue at the end. It might me something I did wrong.
Another thing I saw is the following. I have a Body
field in the Root
object and the Vugu router sets when the URI is /. However, that component is not being rendered.
The issue is in webapp.go
and in particular this code of here
router.MustAddRouteExact("/", vgrouter.RouteHandlerFunc(func(rm *vgrouter.RouteMatch) {
fmt.Println("Setting Root.Body")
root.Body = &Index{}
}))
I am able to see the output Setting Root.Body but the DOM does no change and the Index component is not initialized as Vugu object only as Golang object. Thus, Vugu does not call SetWireFunc
for that component. I don't know if this is wrong or if it is Vugu issue.
Basically the thing is that when I include the Index
component in the root.vugu
as <main:Index></main:Index>
That component is initialized through SetWireFunc
and it is initialized correct. However, if I initialize it in the MustAddRouteExact
callback it does not go through SetWireFunc
.
I'll add all the details down below so it maybe helpful for someone else.
I create a new project from scratch only for testing this. The components are getting wired to the root component but they are not getting injected/wired into the other components.
Let's put the code and the output.
main_wasm.go
the wasm application entrypoint. Here is where Vugu mounts or render the DOM and it calls the VuguSetup
to initialize the webapp.
// +build wasm
package main
import (
"flag"
"fmt"
"github.com/vugu/vugu"
"github.com/vugu/vugu/domrender"
)
func main() {
mountPoint := flag.String("mount-point", "#vugu_mount_point", "The query selector for the mount point for the root component, if it is not a full HTML component")
flag.Parse()
fmt.Printf("Entering main(), -mount-point=%q\n", *mountPoint)
defer fmt.Printf("Exiting main()\n")
buildEnv, err := vugu.NewBuildEnv()
if err != nil {
panic(err)
}
renderer, err := domrender.New(*mountPoint)
if err != nil {
panic(err)
}
defer renderer.Release()
rootBuilder := VuguSetup(buildEnv, renderer.EventEnv())
for ok := true; ok; ok = renderer.EventWait() {
buildResults := buildEnv.RunBuild(rootBuilder)
err = renderer.Render(buildResults)
if err != nil {
panic(err)
}
}
}
webapp.go
, this is where the VuguSetup
function resides. You can see here how in buildEnv.SetWireFunc
I am printing the type of the object I Vugu is about to wire and also the components that Vugu accomplishes to wire.
package main
import (
"fmt"
"github.com/vugu/vgrouter"
"github.com/vugu/vugu"
)
func VuguSetup(buildEnv *vugu.BuildEnv, eventEnv vugu.EventEnv) vugu.Builder {
router := vgrouter.New(eventEnv)
api := &API{}
state := &State{}
buildEnv.SetWireFunc(func(b vugu.Builder) {
fmt.Printf("Wiring: %T\n", b)
if c, ok := b.(vgrouter.NavigatorSetter); ok {
fmt.Println("Setting Router")
c.NavigatorSet(router)
}
if c, ok := b.(APISetter); ok {
fmt.Println("Setting API")
c.APISet(api)
}
if c, ok := b.(StateSetter); ok {
fmt.Println("Setting State")
c.StateSet(state)
}
})
root := &Root{}
buildEnv.WireComponent(root)
router.MustAddRouteExact("/", vgrouter.RouteHandlerFunc(func(rm *vgrouter.RouteMatch) {
fmt.Println("Setting Root.Body")
root.Body = &Index{}
}))
if router.BrowserAvail() {
err := router.ListenForPopState()
if err != nil {
panic(err)
}
err = router.Pull()
if err != nil {
panic(err)
}
}
return root
}
root.vugu
this is the main component. This component has a router (vgrouter.NavigatorRef
), an API (APIRef
), and a Stage (StateRef
).
<div>
<p>Hi!</p>
<main:Index></main:Index>
</div>
<script type="application/x-go">
import (
"github.com/vugu/vgrouter"
)
type Root struct {
vgrouter.NavigatorRef
StateRef
APIRef
Body vugu.Builder
}
func (c *Root) Init() {
fmt.Println("Called: Root Init")
}
</script>
index.vugu
. This component also has a router (vgrouter.NavigatorRef
), an API (APIRef
), and a Stage (StateRef
).
<div>
<p>I'm here!</p>
</div>
<script type="application/x-go">
import (
"github.com/vugu/vgrouter"
)
type Index struct {
vgrouter.NavigatorRef
StateRef
APIRef
}
func (c *Index) Init() {
fmt.Println("Called: Index Init")
}
</script>
api.go
is where the API implementation resides.
package main
type API struct {
Endpoint string
}
type APIRef struct{ *API }
type APISetter interface{ APISet(*API) }
func (cr *APIRef) APISet(c *API) { cr.API = c }
state.go
is where the state implementation resides.
package main
type State struct {
S map[string]interface{}
}
type StateRef struct{ *State }
type StateSetter interface{ StateSet(*State) }
func (cr *StateRef) StateSet(c *State) { cr.State = c }
The output when the Index
component is initialized through SetWireFunc
Entering main(), -mount-point="#vugu_mount_point"
13:00:51.960 wasm_exec.js:51 Wiring: *main.Root
13:00:51.961 wasm_exec.js:51 Setting Router
13:00:51.961 wasm_exec.js:51 Setting API
13:00:51.962 wasm_exec.js:51 Setting State
13:00:51.963 wasm_exec.js:51 Setting Root.Body
13:00:51.967 wasm_exec.js:51 Called: Root Init
13:00:51.968 wasm_exec.js:51 Wiring: *main.Index
13:00:51.968 wasm_exec.js:51 Setting Router
13:00:51.969 wasm_exec.js:51 Setting API
13:00:51.969 wasm_exec.js:51 Setting State
13:00:51.989 wasm_exec.js:51 Called: Index Init
The output when the Index
component is initialized in the router MustAddRouteExact
callback.
Entering main(), -mount-point="#vugu_mount_point"
12:47:16.303 wasm_exec.js:51 Wiring: *main.Root
12:47:16.312 wasm_exec.js:51 Setting Router
12:47:16.312 wasm_exec.js:51 Setting API
12:47:16.314 wasm_exec.js:51 Setting State
12:47:16.318 wasm_exec.js:51 Setting Root.Body
12:47:16.320 wasm_exec.js:51 Called: Root Init
I see, thanks for the detailed explanation. How is the navigation to the "/" page being done? Are you calling Navigate? Or is this just when you first browse to the page, or some other way?
It sounds like there is no render pass that is occurring after the navigation takes place, which should address what you're talking about.
The / is the first place where the browser navigates. And I am using <vg-comp expr="c.Body"></vg-comp>
in the Root
component to render the component assigned during the routing.
I think we are fine to close this as everything is fixed.
Question I am trying to wire 2 components in the
buildEnv.SetWireFunc
method. For that I was following this. The code I come up with is:If you have realized inside
buildEnv.SetWireFunc
there are three conditionals where the argumentb
type ofvugu.Builder
is being casted into different types to see if any of them match. If it does, then a print statement is displaying a message and the setter is called.The
Root
struct looks like this:The Router, State, and API are there. However, I only see
Setting Router
message, instead of all three.Is your question related to a problem? Please describe. No, as far as I know.
Suggested Changes None at the moment
Additional context The setter interface is as defined in the link I said before.