logo Buffalo slack logo
Custom Helpers
Frontend

Custom Helpers

This document only applies when using https://github.com/gobuffalo/buffalo/tree/main/render.

Please see github.com/gobuffalo/plush for more details on the underlying templating package.

No templating package would be complete without allowing for you to build your own, custom, helper functions.

Registering Helpers

Helper functions can be registered in two different places, depending on how they are to be used.

Global Helpers

Most helpers will be global helpers, meaning that they should be included in every template. The types of helpers can can be set in actions/render.go:

func init() {
  r = render.New(render.Options{
    // ...
    Helpers: render.Helpers{
      "myHelper": func() string {
        return "hello"
      },
    },
    // ...
  })
}

Per Request Helpers

Other helpers, that are specific to a certain request can be added to the buffalo.Context for that request.

func HomeHandler(c buffalo.Context) error {
  // ...
  c.Set("myHelper", func() string {
    return "hello"
  })
  // ...
}

Return Values

Plush allows you to return any values you would like from a helper function. This guide will focus on helpers that are designed to generate “output”.

When returning multiple values from a function, the first value will be the one used for rendering in the template. If the last return value is an error, Plush will handle that error.


string

Return just a string. The string will be HTML escaped, and deemed “not”-safe.

func() string {
  return ""
}

template.HTML

https://golang.org/pkg/html/template/#HTML

Return a template.HTML string. The template.HTML will not be HTML escaped, and will be deemed safe.

func() template.HTML {
  return template.HTML("")
}

Input Values

Custom helper functions can take any type, and any number of arguments. You can even use variadic functions. There is an optional last argument, plush.HelperContext, that can be received. It’s quite useful, and I would recommend taking it, as it provides you access to things like the context of the call, the block associated with the helper, etc…

Simple Helpers

r := render.New(render.Options{
  // ...
  Helpers: render.Helpers{
    "greet": func(name string) string {
      return fmt.Sprintf("Hi %s!", name)
    },
  },
  // ...
})

The greet function is now available to all templates that use that render.Engine.

// actions/greet.go
func Greeter(c buffalo.Context) error {
  c.Set("name", "Mark")
  return c.Render(200, r.String("<h1><%= greet(name) %></h1>"))
}
// output
<h1>Hi Mark!</h1>

Block Helpers

Like the if or for statements, block helpers take a “block” of text that can be evaluated and potentially rendered, manipulated, or whatever you would like. To write a block helper, you have to take the plush.HelperContext as the last argument to your helper function. This will give you access to the block associated with that call.

// actions/render.go
r := render.New(render.Options{
  // ...
  Helpers: render.Helpers{
    "upblock": upblock,
  },
  // ...
})
// helper
func upblock(help plush.HelperContext) (template.HTML, error) {
  s, err := help.Block()
  if err != nil {
    return "", err
  }
  return strings.ToUpper(s), nil
}
// actions/upper.go
func Upper(c buffalo.Context) error {
  return c.Render(200, r.HTML("up.html"))
}
// templates/up.html
<%= upblock() { %>
  hello world
<% } %>
// output
HELLO WORLD

Getting Values From the Context

// actions/render.go
r := render.New(render.Options{
  // ...
  Helpers: render.Helpers{
    "is_logged_in": isLoggedIn,
  },
  // ...
})
// helper
func isLoggedIn(help plush.HelperContext) bool {
  return help.Value("current_user") != nil
}
// actions/users.go
func Show(c buffalo.Context) error {
  c.Set("current_user", models.User{Name: "Ringo"})
  return c.Render(200, r.HTML("users/show.html"))
}
// templates/users/show.html
<%= if (is_logged_in()) { %>
  Hello <%= current_user.Name %>
<% } %>
// output
Hello Ringo