Maintainable Perch Templates

Some of your Perch templates might be quite long. For example, a typical product template (using the Perch Shop app) has 20+ Perch tags: the default tags you need to keep and the custom tags you may add.

When you start mixing your HTML with so many Perch tags, it can get a little messy. Firstly, there can be a lot in there: you have Perch tags that contain many attributes that improve your edit form and have no impact on the HTML rendering such as help, size and divider-before as well as other necessary attributes such as id, type and label. Then you got to think about the order of the fields on the edit form (which can be very different from what you need for your markup) so you start adding order attributes to these tags.

1<perch:shop
2 id="short_desc"
3 type="textarea"
4 label="Short Description"
5 markdown="true"
6 editor="markitup"
7 size="s"
8 help="This is displayed above the product options. It should be a concise description that highlights the product's best features"
9 order="4"
10 divider-before="Product Details"
11/>

In small templates, it doesn’t feel like much. You can see where everything is and edit whatever you want quickly. However, in a big template things can get lost especially if you are reviewing a template you had written a while ago.

What you can do

Generally, you need a Perch template for two tasks:

  1. To create (and edit) content/data for an item (product, blog post, etc)

  2. To retrieve content and display it on a page

Perch is very flexible, so you can have a template to create the content and use another template to display it on a page. You can create some separation here to make things more manageable, more maintainable.

Example:

The following Perch Shop function uses the default product template (perch/template/shop/products/product.html):

1perch_shop_product('my-product');

By removing all your markup from the default product template (leaving Perch tags only), it will be easier to manage your edit form. You can move tags around as you wish and not worry about using any order attributes. You can focus on making the edit form more logical and user-friendly for your editors/clients without any HTML in your way. The template will be a lot easier to edit in the future.

As for your markup, create another template just for your frontend (HTML output). You can give it a different name and place it in the same directory as the default template, but I prefer to create a sub-directory named frontend and place the file there.

At render time, we always need the id and the type attributes.

You will still need Perch tags inside your frontend template, but you can delete all the attributes from them except the id and type attributes (always needed).

You can delete all the help and note-before attributes (that may have long explanations), order and divider-before that are also purely for the edit form. You can also delete any Perch tags you don't need in your frontend template rather than using the suppress attribute to hide them.

You'll end up with very short Perch tags and potentially fewer of them. Now you can scan through your markup much faster.

Below is a Perch tag with the ID of short_desc. To put into context: it is a short description of a product. On the product page the editor can add a short description and a detailed one. So by adding the help attribute we can give the editors some tips to differentiate between the two fields.

1<!-- short_desc in template/shop/products/product.html (the template used for the edit form) -->
2<perch:shop
3 id="short_desc"
4 type="textarea"
5 label="Short Description"
6 editor="markitup"
7 markdown="true"
8 size="s"
9 help="This is displayed above the product options. It should be a concise description that highlights the product's best features"
10 divider-before="Product Details"
11/>
12 
13<!-- short_desc in template/shop/products/frontend/product.html (the template used for front-end) -->
14<perch:shop id="short_desc" type="textarea" />

Don't forget to edit your perch_shop_product function:

1perch_shop_product('my-product', [
2 'template' => 'frontend/product.html'
3]);