Meerkat

Meerkat

Responses and Replies

In general, responses are the collection of all comments and replies on any given page of your site. A comment may have its own collection of children comments; these are referred to as replies.

#Overview

The {{ meerkat:responses }} tag is your window into the comment data stored for each of your site's pages. This tag and data structure has a lot in common with Statamic's collection tag, but they should not be used interchangeably when displaying comments; there are a few key differences in the implementations that we will discuss in other guides.

While Meerkat's collection syntax is very close to Statamic's, you should not use Statamic's filter syntax when working with Meerkat threads. Please check out the Basic Filtering guide for more information.

#A Basic Thread

The following code snippet will display all root level comments that are available on the current page as unordered list:

1<ul>
2{{ meerkat:responses }}
3 {{ comments }}
4 <li>{{ author.name }} says... {{ content }}</li>
5 {{ /comments }}
6{{ /meerkat:responses }}
7</ul>

#Available Variables

The following table highlights the data that is available to you by default when developing a Meerkat thread. It should be noted, however, that because of the extensible nature of Meerkat and the customizations that blueprints provide, this is not an exhaustive list:

Variable Description
{{ content }} The comment's content.
{{ author.name }} The name of the comment's author.
{{ author.email }} The email address of the comment's author.
{{ id }} The internal ID of the comment.
{{ date }} A Carbon date instance representing when the comment was submitted.
{{ has_replies }} Indicates whether or not the comment has any replies.
{{ is_reply }} Indicates whether or not the current comment is a reply to someone else's comment.

For a more complete list of the variables that are available to you, consider checking out the Default Variables article.

#Collection Scoping

Comment scoping works in exactly the same was as scoping in Statamic collections; and you can find out more information about how Statamic scoping works by reading the Statamic documentation on scoping. The default scope is named comments, and the scope tags must always be present:

1{{ meerkat:responses }}
2 
3 {{ comments }}
4 
5 {{ /comments }}
6 
7{{ /meerkat:responses }}

Produces the same result as:

1{{ meerkat:responses as="comments" }}
2 
3 {{ comments }}
4 
5 {{ /comments }}
6 
7{{ /meerkat:responses }}

The following values will always be available to you when designing a comment thread:

Variable Description
{{ comments }} A collection containing the comment's replies, if any. The name of this variable will change depending on the scope name.
{{ total_results }} The total number of comments returned by Meerkat.
{{ first }} Indicates whether or not the current comment is the first comment in the collection.
{{ last }} Indicates whether or not the current comment is the last comment in the collection.
{{ zero_index }} The number/index of the current loop iteration, starting at 0.
{{ index }} The number/index of the current loop iteration, starting at 1.
{{ no_results }} Indicates whether or not there are any comments to display. This will be true if total_results is greater than zero.

#No Comment Messages

To offer the best user experience, you may wish to display a message to users to encourage them to leave the first comment on a blog post or page. To do this, we will make use of the no_results value that is available to use when rendering Meerkat threads; this value will indicate if there were any comments found for the current page and filters:

1{{ meerkat:responses }}
2 
3 {{ if no_results }}
4 <p>Be the first to leave a reply!</p>
5 {{ else }}
6 
7 {{ comments }}
8 <!-- Implement your comment thread here. -->
9 {{ /comments }}
10 
11 {{ /if }}
12 
13{{ /meerkat:responses }}

#Recursive Comments (Nested Replies)

Displaying comments recursively, or a nested list, is a common visual pattern on web pages.

This feature relies on the following Statamic pull request: https://github.com/statamic/cms/pull/8421.

Until this is generally available, you will need to pull this in with a composer patch, or recursively include a comment partial.

The following code example demonstrates how to implement nested comments:

1{{ meerkat:responses }}
2 
3<ul>
4 {{ comments }}
5 <li>
6 <p>{{ author.name }} says: {{ content }}</p>
7 
8 {{ if comments }}
9 <ul>{{ *recursive comments* }}</ul>
10 {{ /if }}
11 </li>
12 {{ /comments }}
13</ul>
14 
15{{ /meerkat:responses }}

In the previous example, we implemented a nested comment thread by adding just a few extra lines of code to our template. However, there are a few important things to keep in mind:

#Always Check for Nested Comments

When writing recursive comments, always check if there are nested comments by using a condition similar to the following example:

1{{ comments }}
2 {{ if comments }}
3 {{ *recursive comments* }}
4 {{ /if }}
5{{ /comments }}

#Wrapping our Nested List

When implementing the nested list you may notice that we had to specify the wrapper element again (ul):

1{{ if comments }}
2 <ul class="nested-list">{{ *recursive comments* }}</ul>
3{{ /if }}

This provides you the opportunity to wrap the replies in a custom wrapper element, add additional CSS classes, etc. How you decide to wrap your comment's replies is highly dependent on your project's design. If you were expecting them to be nested visually when using ordered or unordered lists, the nested replies are most likely not wrapped in their own list.

#Scope Variable Names

The name of the collection that is supplied when rendering nested comments is important, and is determined by the current collection alias, or name. The default name is comments, so we implement the nested replies like so by default:

1{{ meerkat:responses }}
2 
3<ul>
4 {{ comments }}
5 <li>
6 <p>{{ author.name }} says: {{ content }}</p>
7 
8 {{ if comments }}
9 <ul>{{ *recursive comments* }}</ul>
10 {{ /if }}
11 </li>
12 {{ /comments }}
13</ul>
14 
15{{ /meerkat:responses }}

If we had renamed the collection to items, we would update the recursive tag like so:

1{{ meerkat:responses as="items" }}
2 
3<ul>
4 {{ items }}
5 <li>
6 <p>{{ author.name }} says: {{ content }}</p>
7 
8 {{ if items }}
9 <ul>{{ *recursive items* }}</ul>
10 {{ /if }}
11 </li>
12 {{ /items }}
13</ul>
14 
15{{ /meerkat:responses }}

#Flat Threads

By default, Meerkat will assume that you will be displaying comments as nested lists. Because of this, the comments that are available in the comments variable will be the root level comments. For example, if there are only two root level comments, but there are twenty total comments, only the two root level comments will be available when iterating the comments collection. You can disable this by supplying a value of true to the flat parameter:

1{{ meerkat:responses flat="true" }}
2 
3<ul>
4 {{ comments }}
5 <li>
6 <p>{{ author.name }} says: {{ content }}</p>
7 </li>
8 {{ /comments }}
9</ul>
10 
11{{ /meerkat:responses }}

When you specify flat="true" Meerkat will internally restructure the comment data structure so that all root level and replies are available at level one.

#Paginated Comments

Meerkat can display your comment threads as a paginated list. Developers familiar with Statamic's collection pagination will be comfortable working with Meerkat's pagination feature. To enable pagination mode when rendering your comment thread, simply add the paginate="true" and a limit to your responses tag:

1{{ meerkat:responses limit="10" paginate="true" }}
2 <!-- The rest of your code goes here. -->
3{{ /meerkat:responses }}

The value supplied to limit controls how many root level comments will be returned by the request; i.e., if your page had twenty total comments, and the limit is set to ten, you will have two pages of ten comments each.

#Pagination Variables

When the Meerkat responses tag is in pagination mode, you will gain access to a new paginate variable that contains useful data that will make it easier to work with paginated comment threads:

Variable Description
{{ next_page }} The URL to this instance's next page.
{{ prev_page }} The URL to this instance's previous page.
{{ total_items }} The total number of comments across all pages.
{{ total_pages }} The total number of paginated pages.
{{ current_page }} The current paginated page; this will match the query parameter for this paginator instance.
{{ auto_links }} Provides ready-made HTML for the paginated results, built on top of Laravel's paginator.
{{ links }} Contains information about each page in the result set to build custom link displays.

The following example demonstrates basic use of the pagination variables:

1{{ meerkat:responses paginate="true" limit="10" }}
2 
3 {{ comments }}
4 <!-- Thread code here. --->
5 {{ /comments }}
6 
7 {{ paginate }}
8 
9 <!-- Create a link to the next page. -->
10 <a href="{{ next_page }}">Next</a>
11 
12 {{ /paginate }}
13 
14{{ /meerkat:responses }}

#Multiple Pagination Instances

In the previous section, you may have noticed that the examples and descriptions were careful to mention that some values apply to the "current instance". This is because Meerkat allows you to have multiple threads on a single page, and if they are paginated, you probably don't want all instances to share the same page query parameter. To have each comment thread instance maintain its own current page value, we can make use of the pageby parameter:

1<!-- Instance One -->
2{{ meerkat:responses paginate="true" limit="10" }}
3 
4 {{ comments }}
5 <!-- Thread code here. --->
6 {{ /comments }}
7 
8 {{ paginate }}
9 
10 <!-- Create a link to the next page. -->
11 <a href="{{ next_page }}">Next</a>
12 
13 {{ /paginate }}
14 
15{{ /meerkat:responses }}
16 
17<!-- Instance Two -->
18{{ meerkat:responses paginate="true" limit="10" pageby="instance2" }}
19 
20 {{ comments }}
21 <!-- Thread code here. --->
22 {{ /comments }}
23 
24 {{ paginate }}
25 
26 <!-- Create a link to the next page. -->
27 <a href="{{ next_page }}">Next</a>
28 
29 {{ /paginate }}
30 
31{{ /meerkat:responses }}

The default value of the pageby parameter is page; the value supplied is what will be used when constructed URLs and when deciding what the current_page value is. In the previous example, the page would now have access to two separate page values, allowing the paginator instances to work independently. If the previous example was rendered with the following URL parameters instance one would be on page one, and instance two would be on page five:

1yoursite.local/dance?page=1&instance2=5

The internal pagination logic will keep track of all the existing query parameters for you, so there are no additional steps to generate pagination links when using multiple instances on one page.

#Date Grouped Comments

Meerkat supports grouping your comments by date out of the box. To utilize this feature, you just need to add the group_by_date parameter with the date format you'd like to use:

1{{ meerkat:responses group_by_date="Y m, d" }}
2 
3 {{ date_groups }}
4 
5 <h3>This group's name is: {{ date_group }}</h3>
6 
7 {{ comments }}
8 <!-- Render the comments in each group. -->
9 {{ /comments }}
10 
11 {{ /date_groups }}
12 
13{{ /meerkat:responses }}

When displaying date grouped comments, you will have access to each group (through date_groups), as well as the following values:

Variable Description
{{ total_count }} The total number of groups.
{{ has_results }} Indicates if there are any comments for the request.
{{ no_results }} Indicates if the comment request is empty.
{{ total_results }} The total number of comments returned in the request.
{{ items_count }} The total number of comments returned in the request.
1{{ meerkat:responses group_by_date="Y m, d" }}
2 
3 {{ date_groups }}
4 
5 <h3>This group's name is: {{ date_group }}</h3>
6 
7 <p>There are {{ total_count }} groups.</p>
8 
9 {{ comments }}
10 <!-- Render the comments in each group. -->
11 {{ /comments }}
12 
13 {{ /date_groups }}
14 
15{{ /meerkat:responses }}

#Group Variables

The following variables are available to you within each group:

Variable Description
{{ comments }} The comment collection; this will change if the scope has been renamed.
{{ count }} Indicates what the current group's number is (one-based index).
{{ index }} The zero-based index of the current group..
{{ first }} Indicates if the group is the first group in the list.
{{ last }} Indicates if the group is the last group in the list.
1{{ meerkat:responses group_by_date="Y m, d" }}
2 
3 {{ date_groups }}
4 
5 {{ comments }}
6 <p>This is group number: {{ count }}</p>
7 
8 <!-- Render the comments in each group. -->
9 {{ /comments }}
10 
11 {{ /date_groups }}
12 
13{{ /meerkat:responses }}

#Paginated Groups

Meerkat 2 introduces the ability to create paginated groups of comments; this feature combines the pagination and grouping features to allow for incredibly customized and complex comment layouts. This feature is intended for advanced use cases; if you are looking to implement a simpler comment thread for your site or client project consider checking out the
A Basic Thread and Recursive Comments (Nested Replies) sections.

While this is an advanced feature, using it is incredibly simple; all you have to do is add the group_by_date and paginate parameters like so:

1{{ meerkat:responses paginate="true" limit="5" group_by_date="Y m, d" }}
2 
3{{ date_groups }}
4 
5 {{ comments }}
6 
7 <!-- Render comment thread here. -->
8 
9 {{ /comments }}
10 
11{{ /date_groups }}
12 
13 
14{{ paginate }}
15 
16 <a href="{{ prev_page }}">Back</a> <a href="{{ next_page }}">Next</a>
17 
18{{ /paginate }}
19 
20 
21{{ /meerkat:responses }}

Internally, comments will first be ordered based on where they would appear in the group list (also taking into consideration any custom sort orders applied) and then split into pages (so a single group may span multiple pages).

You will have access to all of the normal pagination values and all of the group values.

Some absolutely amazing
people

The following amazing people help support this site and my open source projects ♥️
If you're interesting in supporting my work and want to show up on this list, check out my GitHub Sponsors Profile.