The Router
The package github.com/vugu/vgrouter
provides routing functionality for Vugu applications.
A vgrouter.Router
provides functionality for both
server-side (by reading an http.Request) and client-side (by reading the browser's path or #fragment) routing.
If you're not yet familiar with Vugu wiring, you'll likely want to read up on that before continuing.
Routes are registered and when processing are examined in the sequence they were registered.
Matches for routes can be exact or partial and the code for that route can then perform an appropriate action.
The usual approach will be to have one or more sections of your user interface be dynamic based on
which route is currently active. Then the route handler(s) which match for a given route assign those
sections as fields of type vugu.Builder
, which are then rendered via a
vg-comp tag. Let's look at an example. Follow the comments for a
an as-you-go explanation of the parts:
// setup.go package main import ( "path" "strings" "github.com/vugu/vgrouter" "github.com/vugu/vugu" "github.com/vugu/vugu/js" ) // OVERALL APPLICATION WIRING IN vuguSetup func vuguSetup(buildEnv *vugu.BuildEnv, eventEnv vugu.EventEnv) vugu.Builder { // CREATE A NEW ROUTER INSTANCE router := vgrouter.New(eventEnv) // MAKE OUR WIRE FUNCTION POPULATE ANYTHING THAT WANTS A "NAVIGATOR". buildEnv.SetWireFunc(func(b vugu.Builder) { if c, ok := b.(vgrouter.NavigatorSetter); ok { c.NavigatorSet(router) } }) // CREATE THE ROOT COMPONENT root := &Root{} buildEnv.WireComponent(root) // WIRE IT // ADD ROUTES FOR EACH PAGE. NOTE THAT THESE ARE "EXACT" ROUTES. // YOU CAN ALSO ADD ROUTES THAT MATCH ANYTHING WITH THE SPECIFIED PREFIX. router.MustAddRouteExact("/", vgrouter.RouteHandlerFunc(func(rm *vgrouter.RouteMatch) { root.Body = &Page1{} // A COMPONENT WITH PAGE CONTENTS })) router.MustAddRouteExact("/page2", vgrouter.RouteHandlerFunc(func(rm *vgrouter.RouteMatch) { root.Body = &Page2{} // A COMPONENT WITH PAGE CONTENTS })) router.SetNotFound(vgrouter.RouteHandlerFunc( func(rm *vgrouter.RouteMatch) { root.Body = &PageNotFound{} // A PAGE FOR THE NOT-FOUND CASE })) // TELL THE ROUTER TO LISTEN FOR THE BROWSER CHANGING URLS err := router.ListenForPopState() if err != nil { panic(err) } // GRAB THE CURRENT BROWSER URL AND PROCESS IT AS A ROUTE err = router.Pull() if err != nil { panic(err) } return root }
And our Root component which houses the Body field and renders it.
<!-- root.vugu --> <div> <h1>Test App</h1> <!-- RENDER THE BODY --> <vg-comp expr="c.Body"/> <!-- USE Navigator.Navigate() TO CHANGE TO A DIFFERENT URL--> <button @click='c.Navigate("/", nil)'>Home</button> <button @click='c.Navigate("/page2", nil)'>Page2</button> </div> <script type="application/x-go"> import "github.com/vugu/vgrouter" type Root struct { // ANYTHING THAT MUST NAVIGATE NEED ONLY EMBED THIS vgrouter.NavigatorRef // THE BODY COMPONENT, GETS SET BY THE APPROPRIATE ROUTE ABOVE Body vugu.Builder } </script>
TODO: BindParams also exist and should be documented. Also give a more detailed explanation of the Navigator interface (minimal interface of Router that pages need to know about to perform navigation).