The Ghost Themes Developer Hub

Welcome to the Ghost Themes developer hub. You'll find comprehensive guides and documentation to help you start working with Ghost Themes as quickly as possible, as well as support if you get stuck. Let's jump right in!

Get Started    

has

{{has}} Helper - Test if a resource has specific properties

Usage: {{#has tag="value1,value2" author="value"}}
{{#has slug=../slug}} {{#has number="nth:3"}}
{{#has any="twitter, facebook"}} {{#has all="twitter, facebook"}}

Types
Parameters
Attributes

n/a

  • tag (comma separated list)
  • author (comma separated list)
  • number (number, comma separated list, or nth:value)
  • index (number, comma separated list, or nth:value)
  • slug (string)
  • id (string)
  • any (comma separated list)
  • all (comma separated list)

Description

{{#has}} - is like {{#if}} but with the ability to do more than test a boolean. It allows theme developers to ask questions about the current context and provide more flexibility for creating different layouts.

Like all block helpers, {{#has}} supports adding an {{else}} block or using ^ instead of # for negation - this means that the {{#has}} and {{else}} blocks are reversed if you use {{^has}} and {{else}} instead. In addition, it is possible to do {{else has ...}}, to chain together multiple options like a switch statement.

Simple Example

The {{#has}} helper can be combined with internal tags, to display different information for different types of posts. E.g. you can implement a link-style post by adding an internal tag of #link and using the has helper to detect it:

{{#post}}
  {{#has tag="#link"}}
     {{> "link-card"}}
  {{else}}
    {{> "post-card"}}
  {{/has}}
{{/post}}

Usage

The {{#has}} helper currently supports 4 different types of "questions", with more coming soon.

Questions are asked by providing attribute-value pairs, e.g. tag="tag-name". You can pass multiple attributes, and the {{#has}} helper will always treat this as an OR.

E.g. You can look for a post with a slug of "welcome" OR a tag of "getting started":

{{#has slug="welcome" tag="getting-started"}}
  ...Will execute if the slug is welcome OR the tag is getting-started...
{{/has}}

Post tag or author

{{#has tag="photo"}}{{/has}}
{{#has tag="photo, video"}}{{/has}}
{{#has author="Joanna Bloggs"}}{{/has}}

Specifically when inside the context of a post, you can use the {{#has}} helper to find out if the post has a particular tag or author. Both the tag and author attributes take a comma separated list. If you pass multiple values separated by a comma, these will be treated as an OR.

{{#has tag="General, News"}}
  ...Will execute if the post has a tag of General or News...
 {{/has}}

Tag and author matching is a lowercase match on the tag name or author name, which ignores special characters. This behaviour will be upgraded in future to try to match on either slug or name.

Slug or id

{{#has slug="welcome"}}{{/has}}
{{#has slug=../../slug}}{{/has}}
{{#has id=post.id}}{{/has}}

If you're in the context of an object that has a slug (e.g. post, author, tag and navigation items) you can use the {{#has}} helper to do an exact match. Similarly for all objects that have an ID.

You can either pass the {{#has}} helper a string wrapped in quotes, or a path to a data value from else where in the template data. For example, the following code does an exact match on the string "welcome". If the post's slug is the same, the code inside the has helper will execute.

{{#has slug="welcome"}}
  ... do something..
{{/has}}

Alternatively, you can pass a handlebars path, which references a different piece of data to match against:

{{#has slug=../post.slug}}
  ...do something...
{{/has}}

Any or all

The any comparison will return true if any one of the properties is set in the current context, with support for paths and globals:

{{#has any="twitter, facebook, website"}}
{{#has any="author.facebook, author.twitter,author.website"}}
{{#has any="@blog.facebook, @blog.twitter, @labs.subscribers"}}

Similarly, the all comparison will return true only when all of the properties are set:

{{#has all="@labs.subscribers,@labs.publicAPI"}}

Foreach loop number or index

{{#has number="3"}}{{/has}} // A single number
{{#has number="3, 6, 9"}}{{/has}} // list of numbers
{{#has number="nth:3"}}{{/has}} // special syntax for nth item
{{!-- All of these work exactly the same for index --}}

When you're inside a {{#foreach}} loop of any kind, you have access to two special data variables called @index and @number. @index contains the 0-based index or count of the loop, and @number contains a 1-based index. That is each time around the loop these values increase by 1, but @index starts at 0, and @number starts at 1.

The {{#has}} helper will let you check which number/index of the iteration you are on using the 3 different styles of matching shown above. For example, if you have a list of posts and want to inject a special widget partial every 3rd post, you could do so using the nth:3 pattern:

{{#foreach posts}}
  {{#has number="nth:3"}}
     {{> "widget"}}
  {{/has}}
  
  {{> "post-card"}}
{{/foreach}}

Example Code

To determine if a post has a particular author:

{{#post}}
    {{#has author="Joe Bloggs"}}
        ...do something if the author is Joe Bloggs...
    {{/has}}
{{/post}}

To determine if a post has a particular tag:

{{#post}}
    {{#has tag="photo"}}
        ...do something if this post has a tag of photo...
    {{else}}
        ...do something if this posts doesn't have a tag of photo...
    {{/has}}
{{/post}}

You can also supply a comma-separated list of tags, which is the equivalent of an OR query, asking if a post has any one of the given tags:

{{#has tag="photo, video, audio"}}
    ...do something if this post has a tag of photo or video or audio...
{{else}}
    ...do something with other posts...
{{/has}}

You can do an AND query by nesting your {{#has}} helpers:

{{#has tag="photo"}}
    ...do something if this post has a tag of photo..
    {{#has tag="panorama"}}
       ...if the post has both the photo and panorama tags
    {{/has}}
{{else}}
    ...do something with other posts...
{{/has}}

You can also do multiple options, a bit like a switch statement by nesting inside of the {{else}} part of the helper:

{{#has tag="photo"}}
    ...post has the photo tag...
{{else}}
    {{#has tag="video"}}
        ...post has the video tag...
    {{else}}
        {{#has tag="audio"}}
            ...post has the audio tag...
        {{else}}
            ...post has none of the mentioned tags...
        {{/has}}
    {{/has}}
{{/has}}

Negation

If you want to negate the query, i.e. determining if a post does not have a particular tag, this is also possible.

Handlebars has a feature which is available with all block helpers that allows you to do the inverse of the helper by using ^ instead of # to start the helper:

{{^has tag="photo"}}
    ...do something if this post does **not** have a tag of photo...
{{else}}
    ...do something if this posts does have a tag of photo...
{{/has}}

Using paths

You can use the has helper to test against other values in your template. For example, if you've used the get helper to fetch some related posts, you can use the has helper to detect if you're on the current post by testing if the slugs are the same.

{{#post}}
  {{!-- Output main post data --}}
  <h1>{{title}}</h1>
  
  {{!-- Fetch related posts, using the primary tag --}}
  {{#get "posts" filter="tags:{{primary_tag.slug}}" limit="5" as |related|}}
    {{#foreach related}}
      <li>
      {{!-- Check if this post is the same as the main post --}}
      {{#has slug=../../slug}}
        {{title}}
      {{else}}
        <a href="{{url}}">{{title}}</a>
      {{/has}}
    </li>
    {{/foreach}}
  {{/get}}
{{/post}}

The ../ syntax goes back one level in the data. In this case we go back once to get outside of the foreach loop, and then again to move outside of the get helper, and then we are back in the context of our original post.

Switch-style else-has

Imagine if you have a set of special call to actions you want to insert into a post list, one after the 3rd post, one after the 8th and a final one after the 15th. Using {{#has number="3,8,15}} wouldn't work, because we don't want to do the same thing each time. Instead we can use else-has.

We can also pass values to partials, to change what's output.

{{#foreach posts}}
  {{#has number="3"}}
     {{> "advert" title="Foo"}}
  {{else has number="8"}}
     {{> "advert" title="Bar"}}
  {{else has number="15"}}
     {{> "subscribe"}}
  {{/has}}
 
  {{> "post-card"}}
{{/foreach}}

has

{{has}} Helper - Test if a resource has specific properties