HUGO

How to output a “Mustache” syntax JS template from within Hugo

This weekend I spent more time than I anticipated integrating Snipcart to a Hugo site.

Click here for all the nasty details

One of the issues that really wasted my time is the address autocomplete feature in the Snipcart 3x interface.

The idea is lovely, but poorly executed.

Whenever a client starts typing an address in the cart, then results of possible addresses are displayed via Google.

However the address format follows North American conventions and in my case (being in the old world) a Province is a required field and as a result the address selected via Google ended up being invalid.

The only default option offered by Snipcart is a checkbox called ‘I cannot find my address’ so that when ticked another static form is displayed with all mandatory address fields.

Unfortunately Snipcart does not a offer a straightforward setting to disable the above autocomplete.
Instead they advice users to manually override the address components template.

Snipcart is built on Vue, and its templates use the “Mustache” double curly syntax that is incompatible with Hugo templates.

To output a “Mustache” syntax template in a Hugo project, users would need to wrap the markup in backticks, use the print function to convert the template into a string and then pipe it with the safeHTML func, so that the markup is properly formatted and ready for use on the front-end by JS.

Note that the following is possible only in Hugo version 0.81.0 (and later) that introduced support for newlines in template functions

  {{ print `<address-fields>
    <div>
      <fieldset class="snipcart-form__set">
        <div class="snipcart-form__row">
          <div class="snipcart-form__field snipcart-form__cell--large">
            <snipcart-label
              class="snipcart__font--tiny"
              for="address1"
            >{{ $localize('address_form.address1') }}</snipcart-label>
            <snipcart-input name="address1"></snipcart-input>
            <snipcart-error-message name="address1"></snipcart-error-message>
          </div>

        <div class="snipcart-form__field">
          <snipcart-label
            class="snipcart__font--tiny"
            for="city"
          >{{ $localize('address_form.city') }}</snipcart-label>
          <snipcart-input name="city"></snipcart-input>
          <snipcart-error-message name="city"></snipcart-error-message>
        </div>

        <div class="snipcart-form__field">
          <snipcart-label
            class="snipcart__font--tiny"
            for="country"
          >{{ $localize('address_form.country') }}</snipcart-label>
          <snipcart-typeahead type="dropdown" name="country" autocomplete="country"></snipcart-typeahead>
        </div>

        <div class="snipcart-form__row">
          <div class="snipcart-form__field snipcart-form__cell--large">
            <snipcart-label
              class="snipcart__font--tiny"
              for="province"
            >{{ $localize('address_form.province') }}</snipcart-label>
            <snipcart-typeahead type="dropdown" name="province" autocomplete="province state"></snipcart-typeahead>
          </div>

          <div class="snipcart-form__field snipcart-form__cell--tidy">
            <snipcart-label
              class="snipcart__font--tiny"
              for="postalCode"
            >{{ $localize('address_form.postalCode') }}</snipcart-label>
            <snipcart-input name="postalCode"></snipcart-input>
            <snipcart-error-message name="postalCode"></snipcart-error-message>
          </div>
        </div>
      </fieldset>
    </div>
  </address-fields>`
| safeHTML }}
2 Likes