Skip to content

Commit

Permalink
update readme
Browse files Browse the repository at this point in the history
  • Loading branch information
donseba committed Nov 15, 2024
1 parent dce6a7f commit 6af1361
Showing 1 changed file with 76 additions and 102 deletions.
178 changes: 76 additions & 102 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,94 +1,106 @@
# Go Partial
# Go Partial - Partial Template Rendering for Go

A Go package for rendering partial HTML snippets based on specific HTTP headers. It supports nested partials, out-of-band (OOB) partials, template caching, and more.
This package provides a flexible and efficient way to manage and render partial templates in Go (Golang). It allows you to create reusable, hierarchical templates with support for layouts, global data, caching, and more.

## Features

- **Partial Rendering**: Render specific parts of a webpage based on an HTTP header.
- **Nested Partials**: Support for nesting partials within each other.
- **Out-of-Band (OOB) Partials**: Render OOB partials for dynamic content updates without a full page reload.
- **Template Caching**: Optional template caching with concurrency safety.
- **Template Functions**: Support for custom template functions.
- **File System Support**: Use any fs.FS as the template file system.
- **Partial Templates**: Define and render partial templates with their own data and functions.
- **Layouts**: Use layouts to wrap content and share data across multiple partials.
- **Global Data**: Set global data accessible to all partials.
- **Template Caching**: Enable caching of parsed templates for improved performance.
- **Out-of-Band Rendering**: Support for rendering out-of-band (OOB) partials.
- **File System Support**: Use custom fs.FS implementations for template file access.
- **Thread-Safe**: Designed for concurrent use in web applications.

## Installation
To install the package, run:
```bash
go get github.com/donseba/go-partial
```

## Usage
Below are examples demonstrating how to use the partial package in your Go projects.
## Basic Usage

### Basic Usage
```go
package main
Here's a simple example of how to use the package to render a template.

import (
"context"
"net/http"
### 1. Create a Service

"github.com/donseba/go-partial"
)
The Service holds global configurations and data.

func main() {
http.HandleFunc("/", handleRequest)
http.ListenAndServe(":8080", nil)
```go
cfg := &partial.Config{
PartialHeader: "X-Partial", // Optional: Header to determine which partial to render
UseCache: true, // Enable template caching
FuncMap: template.FuncMap{}, // Global template functions
Logger: myLogger, // Implement the Logger interface or use nil
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
// cstom filesystem with the templates for mini website
fsys := &partial.InMemoryFS{
Files: map[string]string{
"templates/index.html": "<html><body>{{.Partials.content }}</body></html>",
"templates/content.html": "<div>{{.Data.Text}}</div>",
},
}

// Create the root partial
p := partial.New("templates/index.html").ID("root").WithFS(fsys)

// Create a child partial
content := partial.New("templates/content.html").ID("content")
content.SetData(map[string]any{
"Text": "Welcome to the home page",
})

// Add the child partial to the root
p.With(content)
service := partial.NewService(cfg)
service.SetData(map[string]any{
"AppName": "My Application",
})
```

// Render the partial based on the request
out, err := p.RenderWithRequest(context.Background(), r)
if err != nil {
http.Error(w, "An error occurred while rendering the page", http.StatusInternalServerError)
return
}
## 2. Create a Layout

w.Write([]byte(out))
}
The Layout manages the overall structure of your templates.
```go
layout := service.NewLayout()
layout.SetData(map[string]any{
"PageTitle": "Home Page",
})
```

### Handling Partial Rendering
### 3. Define Partials

To render only a specific partial based on an HTTP header:
```go
func handleRequest(w http.ResponseWriter, r *http.Request) {
// ... (setup code as before)
Create Partial instances for the content and any other components.

// Render the partial based on the request
out, err := p.RenderWithRequest(context.Background(), r)
```go
func handler(w http.ResponseWriter, r *http.Request) {
// Create the main content partial
content := partial.NewID("content", "templates/content.html")
content.SetData(map[string]any{
"Message": "Welcome to our website!",
})

// Optionally, create a wrapper partial (layout)
wrapper := partial.NewID("wrapper", "templates/layout.html")

layout.Set(content)
layout.Wrap(wrapper)

output, err := layout.RenderWithRequest(r.Context(), r)
if err != nil {
http.Error(w, "An error occurred while rendering the partial", http.StatusInternalServerError)
http.Error(w, "An error occurred while rendering the page.", http.StatusInternalServerError)
return
}

w.Write([]byte(out))
w.Write([]byte(output))
}
```

// Setting the header to request a specific partial
request, _ := http.NewRequest(http.MethodGet, "/", nil)
request.Header.Set("X-Partial", "content")
## Template Files

templates/layout.html
```html
<!DOCTYPE html>
<html>
<head>
<title>{{.Layout.PageTitle}} - {{.Service.AppName}}</title>
</head>
<body>
{{.Partials.content}}
</body>
</html>
```
templates/content.html
```html
<h1>{{.Data.Message}}</h1>
```

## Using Global and Layout Data

- **Global Data (ServiceData)**: Set on the Service, accessible via {{.Service}} in templates.
- **Layout Data (LayoutData)**: Set on the Layout, accessible via {{.Layout}} in templates.
- **Partial Data (Data)**: Set on individual Partial instances, accessible via {{.Data}} in templates.

### Using Out-of-Band (OOB) Partials
Out-of-Band partials allow you to update parts of the page without reloading:
Expand Down Expand Up @@ -146,53 +158,15 @@ p.WithFS(content)

If you do not use a custom file system, the package will use the default file system and look for templates relative to the current working directory.

## API Reference

### Types
`type Partial`

Represents a renderable component with optional children and data.

`type Data`

The data passed to templates during rendering.
```go
type Data struct {
Ctx context.Context
URL *url.URL
Data map[string]any
Global map[string]any
Partials map[string]template.HTML
}
```

### Functions and Methods
- **New(templates ...string) \*Partial**: Creates a new root partial.
- **NewID(id string, templates ...string) \*Partial**: Creates a new partial with a specific ID.
- **(\*Partial) WithFS(fsys fs.FS) \*Partial**: Sets the file system for template files.
- **(\*Partial) ID(id string) \*Partial**: Sets the ID of the partial.
- **(\*Partial) Templates(templates ...string) \*Partial**: Sets the templates for the partial.
- **(\*Partial) SetData(data map[string]any) \*Partial**: Sets the data for the partial.
- **(\*Partial) AddData(key string, value any) \*Partial**: Adds a data key-value pair to the partial.
- **(\*Partial) SetGlobalData(data map[string]any) \*Partial**: Sets global data available to all partials.
- **(\*Partial) AddGlobalData(key string, value any) \*Partial**: Adds a global data key-value pair.
- **(\*Partial) SetFuncs(funcs template.FuncMap) \*Partial**: Sets template functions for the partial.
- **(\*Partial) AddFunc(name string, fn interface{}) \*Partial**: Adds a single template function.
- **(\*Partial) AppendFuncs(funcs template.FuncMap) \*Partial**: Appends template functions if they don't exist.
- **(\*Partial) AddTemplate(template string) \*Partial**: Adds an additional template to the partial.
- **(\*Partial) With(child \*Partial) \*Partial**: Adds a child partial.
- **(\*Partial) WithOOB(child \*Partial) \*Partial**: Adds an out-of-band child partial.
- **(\*Partial) Wrap(renderer \*Partial) \*Partial**: Wraps the partial with another partial.
- **(\*Partial) RenderWithRequest(ctx context.Context, r \*http.Request) (template.HTML, error)**: Renders the partial based on the HTTP request.


### Template Data
In your templates, you can access the following data:

- **{{.Ctx}}**: The context of the request.
- **{{.URL}}**: The URL of the request.
- **{{.Data}}**: Data specific to this partial.
- **{{.Global}}**: Global data available to all partials.
- **{{.Service}}**: Global data available to all partials.
- **{{.Layout}}**: Data specific to the layout.
- **{{.Partials}}**: Rendered HTML of child partials.

### Concurrency and Template Caching
Expand Down

0 comments on commit 6af1361

Please sign in to comment.