router

package
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 14, 2026 License: MIT Imports: 0 Imported by: 0

README

Router Package

Location: /router

GoWebComponents/
├── dom/
├── hooks/
├── state/
├── render/
├── router/           ← YOU ARE HERE
│   ├── doc.go
│   └── router.go
├── fetch/
├── internal/
├── examples/
└── ...

Overview

The router package provides client-side routing for single-page applications (SPAs). It supports both hash-based routing (#/path) and browser history API routing, enabling navigation without full page reloads.

Router Types

Hash Router

Uses URL hash fragments for routing (e.g., example.com/#/about).

Pros:

  • Works without server configuration
  • Compatible with static hosting
  • No server-side setup needed

Cons:

  • Hash in URL (aesthetics)
  • SEO limitations
Browser Router

Uses HTML5 History API for clean URLs (e.g., example.com/about).

Pros:

  • Clean, semantic URLs
  • Better SEO
  • Professional appearance

Cons:

  • Requires server configuration (all routes → index.html)
  • Doesn't work with file:// protocol

Basic Usage

Hash Router Example
import (
    "github.com/monstercameron/GoWebComponents/dom"
    "github.com/monstercameron/GoWebComponents/router"
    "github.com/monstercameron/GoWebComponents/render"
)

func HomePage(props dom.Attrs) *dom.Element {
    return dom.Div(nil,
        dom.H1(nil, dom.Text("Home Page")),
        dom.P(nil, dom.Text("Welcome!")),
    )
}

func AboutPage(props dom.Attrs) *dom.Element {
    return dom.Div(nil,
        dom.H1(nil, dom.Text("About Page")),
    )
}

func NotFound(props dom.Attrs) *dom.Element {
    return dom.Div(nil,
        dom.H1(nil, dom.Text("404 - Page Not Found")),
    )
}

func main() {
    // Create router with routes
    r := router.NewHashRouter(map[string]router.RouteComponent{
        "/":      HomePage,
        "/about": AboutPage,
        "*":      NotFound,  // Catch-all route
    })

    // Render router
    container := js.Global().Get("document").Call("getElementById", "app")
    render.ToElement(r.Render(), container)

    select {}
}
Browser Router Example
func main() {
    r := router.NewBrowserRouter(map[string]router.RouteComponent{
        "/":         HomePage,
        "/about":    AboutPage,
        "/contact":  ContactPage,
        "/products": ProductsPage,
        "*":         NotFound,
    })

    container := js.Global().Get("document").Call("getElementById", "app")
    render.ToElement(r.Render(), container)

    select {}
}

Navigation

Create navigation links with the dom.A element:

func Navigation(props dom.Attrs) *dom.Element {
    return dom.Nav(nil,
        dom.A(dom.Attrs{
            "href": "#/",  // Hash router
        }, dom.Text("Home")),

        dom.A(dom.Attrs{
            "href": "#/about",
        }, dom.Text("About")),

        dom.A(dom.Attrs{
            "href": "#/contact",
        }, dom.Text("Contact")),
    )
}

// For Browser Router, omit the hash
func Navigation(props dom.Attrs) *dom.Element {
    return dom.Nav(nil,
        dom.A(dom.Attrs{
            "href": "/",  // Browser router
        }, dom.Text("Home")),

        dom.A(dom.Attrs{
            "href": "/about",
        }, dom.Text("About")),
    )
}
Programmatic Navigation

Navigate programmatically using JavaScript:

handleLogin := hooks.GoUseFunc(func(e dom.GoEvent) {
    e.PreventDefault()

    // Perform login logic
    if loginSuccessful {
        // Navigate to dashboard
        js.Global().Get("location").Set("hash", "/dashboard")
        // OR for browser router:
        // js.Global().Get("history").Call("pushState", nil, "", "/dashboard")
    }
})

Dynamic Routes

URL Parameters

Parse URL parameters manually:

func UserProfile(props dom.Attrs) *dom.Element {
    // Get current hash
    hash := js.Global().Get("location").Get("hash").String()

    // Parse user ID from hash like #/users/123
    parts := strings.Split(hash, "/")
    userID := parts[len(parts)-1]

    return dom.Div(nil,
        dom.H1(nil, dom.Text("User Profile")),
        dom.P(nil, dom.Text("User ID: "+userID)),
    )
}

// Register with pattern
routes := map[string]router.RouteComponent{
    "/users":  UsersList,    // List all users
    "/users*": UserProfile,  // Match /users/anything
}
Query Parameters
func SearchResults(props dom.Attrs) *dom.Element {
    // Get URL search params
    url := js.Global().Get("location").Get("href").String()
    // Parse query: #/search?q=golang&sort=relevance

    return dom.Div(nil,
        dom.H1(nil, dom.Text("Search Results")),
        // Display results
    )
}

Layouts

App Layout with Router
func AppLayout(props dom.Attrs) *dom.Element {
    r := router.NewHashRouter(map[string]router.RouteComponent{
        "/":        HomePage,
        "/about":   AboutPage,
        "/contact": ContactPage,
        "*":        NotFound,
    })

    return dom.Div(nil,
        Navigation(nil),  // Always visible nav
        dom.Main(nil,
            r.Render(),   // Routed content
        ),
        Footer(nil),      // Always visible footer
    )
}

func Navigation(props dom.Attrs) *dom.Element {
    return dom.Nav(dom.Attrs{"class": "navbar"},
        dom.A(dom.Attrs{"href": "#/"}, dom.Text("Home")),
        dom.A(dom.Attrs{"href": "#/about"}, dom.Text("About")),
        dom.A(dom.Attrs{"href": "#/contact"}, dom.Text("Contact")),
    )
}

func Footer(props dom.Attrs) *dom.Element {
    return dom.Footer(nil,
        dom.P(nil, dom.Text("© 2024 My App")),
    )
}

Protected Routes

func ProtectedRoute(component router.RouteComponent) router.RouteComponent {
    return func(props dom.Attrs) *dom.Element {
        isAuthenticated, _ := state.UseAtom("user-authenticated", false)

        if !isAuthenticated() {
            // Redirect to login
            js.Global().Get("location").Set("hash", "/login")
            return dom.Div(nil, dom.Text("Redirecting..."))
        }

        return component(props)
    }
}

// Usage
routes := map[string]router.RouteComponent{
    "/":         HomePage,
    "/login":    LoginPage,
    "/dashboard": ProtectedRoute(DashboardPage),
    "/settings":  ProtectedRoute(SettingsPage),
}

Server Configuration

For Browser Router

Configure your server to serve index.html for all routes:

Nginx:

location / {
    try_files $uri $uri/ /index.html;
}

Apache (.htaccess):

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
</IfModule>

Go HTTP Server:

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    http.ServeFile(w, r, "./static/index.html")
})

Best Practices

1. Use Catch-All Route

Always include a * route for 404 pages:

routes := map[string]router.RouteComponent{
    "/": HomePage,
    "*": NotFoundPage,
}
func NavLink(props dom.Attrs) *dom.Element {
    href := props["href"].(string)
    text := props["text"].(string)

    currentHash := js.Global().Get("location").Get("hash").String()
    isActive := currentHash == href

    className := "nav-link"
    if isActive {
        className += " active"
    }

    return dom.A(dom.Attrs{
        "href":  href,
        "class": className,
    }, dom.Text(text))
}
3. Route Constants
const (
    RouteHome    = "/"
    RouteAbout   = "/about"
    RouteContact = "/contact"
)

routes := map[string]router.RouteComponent{
    RouteHome:    HomePage,
    RouteAbout:   AboutPage,
    RouteContact: ContactPage,
}

Examples

See routing in action:

Documentation

See doc.go for the official Go package documentation.

Documentation

Overview

Package router provides client-side routing for single-page applications built with GoWebComponents.

This package implements hash-based and history-based routing with support for:

  • Multiple router instances
  • Route guards (beforeEnter)
  • Browser history integration
  • Programmatic navigation
  • Route-specific page titles

Basic usage with hash routing:

import "github.com/monstercameron/GoWebComponents/router"

func main() {
    r := router.NewHashRouter()

    r.RegisterRoute("/", HomePage)
    r.RegisterRoute("/about", AboutPage)
    r.RegisterRoute("/contact", ContactPage)
    r.RegisterRoute("*", NotFoundPage) // Wildcard for 404

    // Render the current route
    render.To(r.GetRoute(), "#app")
}

Route components are regular components:

func HomePage(props dom.Attrs) *fiber.Element {
    return dom.Div(nil,
        dom.H1(nil, "Welcome Home"),
        dom.A(map[string]interface{}{
            "onclick": js.FuncOf(func(this js.Value, args []js.Value) interface{} {
                router.Navigate("/about")
                return nil
            }),
        }, "Go to About"),
    )
}

Route options:

r.RegisterRoute("/admin", AdminPanel, router.Options{
    Title: "Admin Panel",
    BeforeEnter: func(path string) bool {
        return isAuthenticated() // Return false to prevent navigation
    },
})

The package supports both hash-based routing (using URL fragments like #/about) and history-based routing (using the HTML5 History API).

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetCurrentPath

func GetCurrentPath() string

GetCurrentPath returns the current route path from the global router.

func GetRoute

func GetRoute() *render.Element

GetRoute returns the component for the current route as an Element.

func Navigate(path string)

Navigate updates the URL using the appropriate method for the current router.

Example
// Navigate to a new path
// This works with both hash and history routers
router.Navigate("/about")
func NavigateReplace(path string)

NavigateReplace replaces the current history entry using the appropriate method for the current router.

func RegisterRoute

func RegisterRoute(path string, component interface{}, options ...Options)

RegisterRoute registers a route with the global router.

func RouteWithElement

func RouteWithElement(path string, elemRef js.Value)

RouteWithElement renders a route directly to a DOM element and sets up hash listening.

Types

type Component

type Component = func(dom.Attrs) *render.Element

Component is a type alias for component functions used in routing.

type Options

type Options struct {
	Title string
}

Options represents configuration for individual routes. Placeholder for future per-route settings (e.g., titles, guards).

type Router

type Router struct {
	// contains filtered or unexported fields
}

Router manages routes and navigation for single-page applications.

func GetRouter

func GetRouter() *Router

GetRouter returns the global router instance.

func NewHashRouter

func NewHashRouter(options ...RouterOptions) *Router

NewHashRouter creates a hash-based router that reads from window.location.hash.

Example
// Create a new hash-based router
r := router.NewHashRouter()

// Define page components
homePage := func(props dom.Attrs) *render.Element {
	return dom.Div(nil, dom.H1(nil, dom.Text("Home")))
}

aboutPage := func(props dom.Attrs) *render.Element {
	return dom.Div(nil, dom.H1(nil, dom.Text("About")))
}

// Register routes
r.GoRegisterRoute("/", homePage)
r.GoRegisterRoute("/about", aboutPage)

// In a real app, you would mount the router to the DOM
// r.Mount("#app")

func NewRouter

func NewRouter(options RouterOptions) *Router

NewRouter creates a history-based router using the HTML5 History API. This router uses window.location.pathname instead of hash fragments. Requires server to redirect all routes to the app's entry point.

func (*Router) Current

func (r *Router) Current() *render.Element

Current returns the current route element.

func (*Router) GetCurrentRouterPath

func (r *Router) GetCurrentRouterPath() string

GetCurrentRouterPath returns the current path from a router instance based on its type.

func (*Router) GoGetRoute

func (r *Router) GoGetRoute() *render.Element

GoGetRoute returns the element for the current route.

func (*Router) GoRegisterRoute

func (r *Router) GoRegisterRoute(path string, component interface{}, options ...Options)

GoRegisterRoute registers a route on the router instance.

func (*Router) Mount

func (r *Router) Mount(selector string)

Mount renders the router into a DOM node selected by CSS selector and wires hashchange listeners.

func (*Router) MountElement

func (r *Router) MountElement(elem js.Value)

MountElement renders the router into an existing DOM element reference.

func (*Router) Navigate

func (r *Router) Navigate(path string)

Navigate navigates to a path using the appropriate method for this router type.

func (*Router) NavigateReplace

func (r *Router) NavigateReplace(path string)

NavigateReplace replaces the current history entry using the appropriate method for this router type.

func (*Router) Register

func (r *Router) Register(path string, component interface{}, options ...Options)

Register registers a route using either a component function or a static node.

type RouterOptions

type RouterOptions struct {
	DefaultRoute string
}

RouterOptions configures router defaults.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL