Documentation You are here: start » v » 2.0 » templates » advanced

Advanced Template Customisations

Working with FoxyCart Templates

This section is for people with intermediate to advanced CSS, HTML, and JS abilities. We're happy to help you if you get stuck, but if it's your first rodeo, this stuff might be a bit head-spinning :)

Getting even more advanced with Twig

If you'd like to customize your templates beyond what you can do with HTML, CSS, and JavaScript, FoxyCart allows you to use the Twig template language as well. Twig is flexible template language that's either near identical or relatively similar to a variety of other template languages. This functionality is very advanced, and most users should be able to achieve very seamless visual integrations without this. If you have super specific needs, however, you can dig into Twig.

Templates and Caching: How it all works

  • We use Twig as a template language, and we use Twig.js as well. Doing this allows us (and you) to use the same templates for clientside and serverside rendering.
  • We use the BEM methodology for CSS naming.
  • All template variables used exist in the FC.json object. You'll see references to variables in the template files. That's where they live, but there are helper methods to work with that data.
  • We have a system we call AutoMagiCache, which scrapes a template file on your site and will cache it (and all assets) securely on our systems, so you don't need SSL on your own server to reference assets (images, css, js). Details on working with AutoMagiCache here.
  • We're currently using Twitter Bootstrap 3 as a base for our default theme, but we're using SASS @extend functionality so you won't see any Bootstrap classnames.
  • Doing advanced customizations can get involved, but there are “easier” and “more difficult” ways to accomplish things within our templating approach. When in doubt please, please just reach out. We're happy to help.

Additionally, in previous versions of FoxyCart there was no clear separation of concerns between content (HTML), presentation (CSS), and dynamic behavior (Javascript). With v2.0 we're doing our best to help each aspect be a separate concern, so that you can override or customize the specific aspects your customers need without worrying about breaking things.

Before you proceed any further, we recommend looking over our Templates and Caching Primer page to get an understanding of the different pieces involved. Some parts may be already familiar to you - but having a grasp of the different pieces of the puzzle will make working deep within our templates all the more easier.

We also strongly recommend taking a look at the Twig overview documentation over at their site at https://twig.symfony.com/doc/2.x/templates.html. Understanding the basics of Twig will help you to be able to read our templates.

Below, you'll find our best attempt at explaining each aspect of our templates and how you can override, hook into, or remove the aspects that you're interested in. If you have questions, please don't hesitate to contact our support.

FoxyCart Template Structure

There are two levels to the FoxyCart templates, both of which are rendered using the Twig templating language, which are the Page Templates and the Partial Includes.

Page Templates

The Page Templates are the templates that form the base of the actual page being output - this is where you'll find html, head and body tags. These are also the templates that you'll find under the 'templates' menu in your store's FoxyCart administration. These templates are also the different steps to the checkout flow that a customer could experience.

The Page Templates include:

  • Cart Include
  • Cart - Full page cart (yourstore.foxycart.com/cart)
  • Checkout
  • Receipt
  • Email (HTML and Text)

One key thing to note is the “Cart Include” template. It is technically a partial include template - but is used for the Sidecart functionality on your own website, so is a page template in that regard. The template also performs duties as the cart partial as displayed within the cart, checkout, receipt and HTML email templates though as well. The “Cart Include” template therefore doesn't have the traditional HTML structure in terms of html, head or body tags.

Partial Include Templates

Within the page templates, are one or more partial includes that output different sections of the respective templates. Partials can also be stacked - a given partial may include one or more other partials within itself if required. The different partials may seem confusing at first - but we've broken the templates up into modular reusable pieces. As a quick overview of the different partials includes we have, look over the following cascading lists of our partials as they're included.

  • cart.inc.twig
    • svg.inc.twig
    • errors.inc.twig
    • postal_code.inc.twig
      • regions.inc.twig
  • checkout.inc.twig
    • cart.inc.twig
    • errors.inc.twig
    • address.checkout.inc.twig
      • postal_code.inc.twig
        • regions.inc.twig
  • receipt.inc.twig
    • cart.inc.twig
    • address.receipt.inc.twig
      • postal_code.inc.twig
        • regions.inc.twig
  • address.email.inc.twig - included in responsive.email.twig
  • address.email.inc.txt.twig - included in email.txt.twig
  • cart.inc.txt.twig - included in email.txt.twig

Outputting Partial Includes

A page template on it's own is just a normal page. If you want to include FoxyCart functionality within it, you'll need to output one or more partial includes within the template. You can output a Twig include file in one of two ways, include and use. Which you use will depend on what you're wanting to do.

Include - directly output the include into the page

If you use include, that will take the whole contents of that file, and output it at that spot in the template. This is perfect if you're just wanting to output the default approach to that section, but you're wanting to include it somewhere specific. View include in the Twig documentation.

Example:

{% include 'cart.inc.twig' %}

Embed - output the include on the page, but allowing for overriding blocks within it

Loading an include using embed behaves similar to include above in that it will output the whole contents of the file into the page. Within the embed tags though, you can also define block tags for blocks that exist within that included file, and overwrite them. Any code not contained with a pre-existing block, or any custom blocks, will be ignored. View embed in the Twig documentation.

Example:

{% embed 'checkout.inc.twig' %}
{% endembed %}

Use - load the blocks contained within ready for placement and modifying

Referencing an include using use, with just that tag in isolation will output nothing into the page. What it will do is gather all the blocks within that include and load them into memory for you to manually include as desired. Anything not contained inside blocks will be ignored. View use in the Twig documentation.

Example:

{% use 'cart.inc.twig' %}
{# Nothing output yet #}
{{ block('logo') }}
{# Logo block output into page #}

Blocks

Within the partial templates, we make use of Twig's block functionality to wrap certain chunks of our code into a named block. For an example, let's say you have a partial include called widgets.inc.twig with blocks that look like this:

{% block block_a %}
    <div class="title-container">
        <h1>{{ widget_title }}</h1>
        <img src="{{ widget_image }}" />
    </div>
{% endblock block_a %}
{% block block_b %}
    <h2>{{ widget_subtitle }}</h2>
{% endblock block_b %}

As you can see, there are two blocks within that markup enclosing two headers. If you wanted to just include that whole partial in your page template, you would just use the include approach to do that. What if you wanted to include that partial, but make some changes to one of the blocks? That's where use comes into play - allowing you to reference whole blocks with a single tag.

Editing blocks with ''embed''

As an example, let's say that we wanted to output our widgets.inc.twig partial within our page, but we wanted to change block_b to output the widget_subtitle in a paragraph tag instead of a heading. We don't want to change block_a at all. We could simply copy the whole widgets.inc.twig code into our partial and just ignore the blocks, which would work. A better way though is to make use of the embed tag, and overwrite blocks from the partial. By doing that - our code is cleaner within our page template, and if we make changes to our widgets.inc.twig partial file later on, we'll still get those changes (apart from anything we overwrite).

So to follow on with our example, changing the h2 element to a paragraph would look like this in our page template:

{% embed 'widgets.inc.twig' %}
    {% block block_b %}
        <p>{{ widget_subtitle }}</p>
    {% endblock block_b %}
{% endembed %}

In the code above - the widgets.inc.twig template will be output as it is in the original file, but block_b will be output as we redefined it within the embed. This would result in HTML like this:

<div class="title-container">
    <h1>{{ widget_title }}</h1>
    <img src="{{ widget_image }}" />
</div>
<p>{{ widget_subtitle }}</p>

Embedding also allows you to still output the block as it is - and just add something before or after it. For example, if we wanted to add some additional content after the h2 title in block_b, but leave the heading as it is, we can do that by outputting {{ parent() }} like this:

{% embed 'widgets.inc.twig' %}
    {% block block_b %}
        {{ parent() }}
        <p>{{ widget_date }}</p>
    {% endblock block_b %}
{% endembed %}

This set up would result in HTML like this:

<div class="title-container">
    <h1>{{ widget_title }}</h1>
    <img src="{{ widget_image }}" />
</div>
<h2>{{ widget_subtitle }}</h2>
<p>{{ widget_date }}</p>

If you're wanting to make changes to how the cart template is displayed on the checkout or receipt - you should make changes directly to the “cart include” template. We don't currently support using an embed tag of the cart.inc.twig template within the checkout or receipt embed calls.

Allowed Twig Tags and Functionality

At present, the only allowed functionality for Twig is as follows:

Need a tag, filter or function not listed here? Simply get in touch and we can look at adding it.

We also have some custom Twig filters and functions we've added to meet specific needs:

Tags

money_format
Description: Formats a given number into the formatting of the store
Example: {{ total_item_price|money_format }}
pad
Description: Adds a specific character
Parameters:
  • Integer representing the length to pad (Default 30)
  • String of the value to pad the variable with (Default " ")
  • String of the delimiter between the variable and the padding (Default ":")
  • Direction of the padding from the variable "left" or "right" (Default "right")
Example: {{ key|pad(20) }} or {{ key|pad(30, "-", "", "left") }}
fc_output_data
Description: Used to customise email subjects, from and bcc, as documented here.

Functions

selected
Description: Used to add the selected HTML attribute to select dropdowns
Parameters: Two strings for comparison
Example: <option value="{{ value }}" {{ selected(saved_value, value) }}>
checked
Description: Used to add the checked HTML attribute to checkboxes and radio inputs
Parameters: Boolean to equal true if the input should be checked
Example: <input type="checkbox" name="my_checkbox" value="1" {{ checked(my_checkbox == '1') }} />
formatCityOption
Description: Used to return a city/state string
Params: Object containing city, and optionally region and region_name
Example: {{ formatCityOption({"city": "Nashville", "region": "TN", "region_name": "Tennessee"}) }}
getPostalCodeLabel
Description: Used to get the correct language string for a given countries state or postcode
Parameters: String representing 2 character country code
Example: {{ getPostalCodeLabel(address.country) }}
generate_sso_token
Description: Used to generate a SSO token useful for quick purchases from the receipt or reverse SSO logins, as documented here.
Example: {{ generate_sso_token(timestamp) }}
Notes: Only generated server-side, won't run with client-side Twig.js

Accessing FoxyCart's Templates

All of our page and partial templates are available from our 2.0 templates Github Repository. You can simply use the repository to view the different templates and copy out the templates that you need. If you're familiar with Git though, you can also fork our repository and apply any changes to the templates as needed - and when we apply any updates you can merge those new commits into your edited templates to keep your custom templates up to date.

If you're customising any of the partial includes, you can be updated of changes to the templates in a few ways. Firstly, you can “star” or “watch” the repository to receive notifications through Github. You can also view a RSS feed of all commits to the repository in a RSS viewing tool.

Errors

A big part of an online checkout is error handling. We have some conventions and helper functions if you'd like to customize error handling.

Required Fields & Inline Errors

Required fields will generate an error if a user tabs off of them. Our goal in FoxyCart 2.0 has been to create a default client-side validation system that unobtrusively alerts users to problems with the form, while also giving you as much room to customize as possible. With that in mind inline errors now have three parts:

  1. Field highlighting
  2. Error bar updating
  3. Error event firing

Each of these parts are designed to be independent so you can utilize just one or both in whichever way works best for you. Below you'll find in depth explorations of each step.

1. Field Highlighting

The specific field will be highlighted by adding a class to the element, which allows CSS styling to highlight the field. FoxyCart gives you flexibility in customizing both the error class applied, and which element it is applied to through the use of data attributes. The error class is defined with the data-fc-error-class attribute.

If you are adding the error class to an element other than the input (such as a parent element), then you need to include a data-fc-error-for attribute on that element, with the value being the name of the input. So for the shipping first name field, the parent

has both attributes, looking like this:: data-fc-error-class=“invalid” data-fc-error-for=“shipping-last-name”. In case of an error on the field, the class invalid will be added to the

, and once the error is resolved, the class will be removed.

data-fc-error-class is required if you wish to utilize the FoxyCart inline-error functionality. If no class is found, a fallback method of rerendering the block will be triggered. For the default templates, the fallback method will evaluate the twig context, find the error, and apply the styling to the field. This rerendering is expensive from a browser perspective, so we attempt to avoid it whenever possible.

The data-fc-error-for is not required on the input itself - you can just add the data-fc-error-class attribute alone and FoxyCart will apply it to the input when an error occurs.

Error classes are cleared in the same way they are added: FoxyCart checks the input to see if it has a data-fc-error-class attribute and removes the defined class from the input, if present, and then checks for a data-fc-error-for=“FIELD_NAME” and if one is found, removes the data-fc-error-class defined on the element, if present.

The data-fc-error-class typically just takes a single class name as a string, but an additional “success” class can be added after a comma, like this:

<div class="alert alert-danger"
    data-fc-error-for="cc_cvv2"
    data-fc-error-class="show,hidden"></div>

This will not only add the show class on error, but it will also remove the hidden class as well. When the error is cleared, it will toggle show off and toggle hidden on.

2. Error bar updating

Once the field markup has been updated, FoxyCart updates the notifier bar at the top of the page to alert the user that a field has an error on it. This only occurs if the notifier bar is present. The markup for the bar is very simple, here's what it looks like in the default checkout template:

<section data-fc-error-notifier>
  <h3 data-fc-notifier-text></h3>
</section>

The data-fc-error-notifier attribute needs no value. Adding it to an element tells FoxyCart that all error messages should be added to this element. The data-fc-notifier-text attribute is optional, by default the message will be appended as a <p> element, if you wish to use a different text element, use the data-fc-notifier-text attribute.

When a message is sent to the notifier bar, it checks the length of FC.JSON.messages.errors, and if there are errors present, the bar updates the count and adds the classes “alert alert-danger.” All appearance and animations are handled with CSS and can be defined/overridden in your custom style sheets.

Class that is appended to be active user-definable.

3. Error Event Firing

The last step in error handling is firing a jQuery event that you can listen for to add your own customizations. notificationUpdate is fired on the <body> tag every time a message is sent or removed from FC.JSON.messages.errors. Listening for this event allows you to design custom ways of alerting the user that there are errors on the form, such as jGrowl or something custom.

Hard errors more info coming soon

Site Tools