Controllers

Basic Usage

The controller files are all organized under the controller folder. The controllers handle the interactions between the models and the views as well as specify which routes to map to which functions.

It’s a good idea to follow a naming convention for the different pieces. Laravel developers will notice it’s very similar, but with a few changes.

Method Path Function View
GET /notepad Index index.tmpl
GET /notepad/create Create create.tmpl
POST /notepad/create Store
GET /notepad/view/:id Show show.tmpl
GET /notepad/edit/:id Edit edit.tmpl
PATCH /notepad/edit/:id Update
DELETE /notepad/:id Destroy

Here is a controller that follows the naming convention. Notice the model name (note) matches the view folder (note/index). The model does not need to match the controller because you’ll be working with many different models in your controllers.

func Load() {
	...
	// "Get" is the Method
	// "/notepad" is the Path
	router.Get("/notepad", Index, acl.DisallowAnon)
	...
}

// Index displays the items.
func Index(w http.ResponseWriter, r *http.Request) {
	c := flight.Context(w, r)

	items, _, err := note.ByUserID(c.DB, c.UserID)
	if err != nil {
		c.FlashError(err)
		items = []note.Item{}
	}

	v := c.View.New("note/index")
	v.Vars["items"] = items
	v.Render(w, r)
}

Access a Session

Sessions provide access to flash messages as well as variables that are set at login. You must remember to save the sessions once you make a change to them.

// Get the current session
sess, _ := session.Instance(r)
...
// Save the session after you are finished making changes
sess.Save(r, w)

Trigger Flash Message

Flash messages will appear to the user on next page load. They only display once. The built-in messages are tied to Bootstrap classes:

  • flash.Success is green (alert-success)
  • flash.Warning is yellow (alert-warning)
  • flash.Notice is blue (alert-info)
  • flash.Error is red (alert-danger)
sess.AddFlash(flash.Info{"Welcome to Blueprint!", flash.Success})
sess.Save(r, w) // Ensure you save the session after making a change to it

Validate a Form

The form package makes it easy to validate required fields. It works on the inputs: text, textarea, checkbox, radio, and select. The function, form.Required(), requires the request and then any number of fields as it is a variadic function. You can use the form package by itself it you want more control over the error message or you can use the flight package which handles the error message for you:

// Without flight
if valid, missingField := form.Required(r, "email", "password"); !valid {
	sess.AddFlash(flash.Info{"Field missing: " + missingField, flash.Error})
	sess.Save(r, w)
	LoginGET(w, r)
	return
}

// With flight
c := flight.Context(w, r)
if !c.FormValid("name", "email", "password") {
	Create(w, r)
	return
}

Repopulate Form Fields

The form package can also repopulate the form fields after a submission that is missing information. It is also a variadic function so it can accepts more than one field. You’ll need to use blocks from the form package in your view as well. Check out the Views page to see how to use them.

// Without flight
c := flight.Context(w, r)
v := c.View.New("note/create")
form.Repopulate(r.Form, v.Vars, "name")
v.Render(w, r)

// With flight
c := flight.Context(w, r)
v := c.View.New("note/create")
c.Repopulate(v.Vars, "name")
v.Render(w, r)

Render a Template

You can render a template a few ways (check out the Views page for more clarification):

// Render without adding any variables
c := flight.Context(w, r)
c.View.New("about/index").Render(w, r)

// Render with variables
c := flight.Context(w, r)
v := c.View.New("home/index")
v.Vars["first_name"] = c.Sess.Values["first_name"]
v.Render(w, r)

// Render with different base template (base.tmpl is used by default)
c := flight.Context(w, r)
v := c.View.New("home/index").Base("single")
v.Render(w, r)

Return Flash over Ajax

If you’re using Ajax to retrieve content, you can also retrieve the flash messages this way so they can be displayed without refreshing the page. There is JavaScript that is already designed to show a Flash message and it’s called: ShowFlash(). You’ll just need to make a call to the page and then pass the output to ShowFlash(). The code is below.

Code for the controller:

// Load the routes.
func Load() {
	router.Get("/flashes", Index)
}

// Index displays the flash messages in JSON.
func Index(w http.ResponseWriter, r *http.Request) {
	c := flight.Context(w, r)

	// Set the flash message
	c.Sess.AddFlash(flash.Info{"An error occurred on the server. Please try again later.", flash.Error})
	c.Sess.Save(r, w)

	// Display the flash messages as JSON
	flash.SendFlashes(w, r)
}

Code in JavaScript:

$.get("/flashes", function(data) {
	showFlash(data);
});

Interact with a Model

The models contain all the SQL code so the controllers just call the model functions to interact with the data.

// Get database result
result, norows, err := user.ByEmail(email)

if nowrows {
	// User does not exist
} else if err != nil {
	// Display error message
} else if passhash.MatchString(result.Password, password) {
	// Password matches!
} else {
	// Password does not match
}

Send an Email

There is also a simple package that sends emails once the SMTP settings in env.json point to your SMTP server.

// Email a user
c := flight.Context(w, r)
err := c.Config.Email.Send("This is the subject", "This is the body!")
if err != nil {
	c.FlashError(err)
	return
}