Events Query
The calendar.events template query fetches a list of events based on some or no criteria.
Parameters
rangeStart
- Selects events that fall into a given date range. Defaults to no date (beginning of time) - if you wish to display events from long ago, we do recommend using a value like
6 months ago
or5 years ago
, etc to avoid running into potential performance issues or quirkiness. A date range of2023-01-01
to2023-02-15
would show all events and their recurrences that occur between January 1, 2023 to February 15, 2023. A start range of2023-01-01
with no end range would show all events and their recurrences that occur January 1, 2023 and beyond. - Time ranges can be specified as 24hr or 12hr:
2023-01-01 16:30
or2023-01-01 5:00 pm
- Times consider any events with a duration that overlaps (even partially) with the time range specified.
- Used in conjunction with rangeEnd parameter.
- Alternately, use one of the following instead to have a more precise timeframe (you may need to continue to use
rangeStart
andrangeEnd
parameters if results are not reliable enough when using with recurring events):startsAfter: "now"
startsAfterOrAt: "now"
startsBefore: "now"
startsBeforeOrAt: "now"
- Selects events that fall into a given date range. Defaults to no date (beginning of time) - if you wish to display events from long ago, we do recommend using a value like
rangeEnd
- Selects events that fall into a given date range. Defaults to no date (end of time) - if you wish to display events far into the future, we do recommend using a value like
+6 months
or+5 years
, etc to avoid running into potential performance issues or quirkiness. A date range of2023-01-01
to2023-02-15
would show all events and their recurrences that occur between January 1, 2023 to February 15, 2023. An end range of2023-02-15
with no start range would show all events and their recurrences that occur February 15, 2023 and earlier. - Time ranges can be specified as 24hr or 12hr:
2023-01-01 16:30
or2023-01-01 5:00 pm
- Times consider any events with a duration that overlaps (even partially) with the time range specified.
- Used in conjunction with rangeStart parameter.
- Alternately, use one of the following instead to have a more precise timeframe (you may need to continue to use
rangeStart
andrangeEnd
parameters if results are not reliable enough when using with recurring events):endsAfterOrAt: "now"
endsAfter: "tomorrow"
endsBefore: "now"
endsBeforeOrAt: "now"
- Selects events that fall into a given date range. Defaults to no date (end of time) - if you wish to display events far into the future, we do recommend using a value like
calendar
- Handle of the calendar, e.g.
"holidays"
, or an array of handles:["holidays", "football"]
. - Use
"not holidays"
to select all calendars EXCEPT the Holidays calendar
- Handle of the calendar, e.g.
calendarId
- An ID of the calendar, or array of ID's, e.g.
[1, 2, 3]
- If you want to select all calendars EXCEPT the calendar with an ID of 1, use
"not 1"
- Exclude multiples with syntax like:
calendarId: ["and", "not 1", "not 2"]
- An ID of the calendar, or array of ID's, e.g.
id
- An event ID, or array of ID's, e.g.
[1, 2, 3]
- If you want to select all events EXCEPT the event with an ID of 1, use
"not 1"
- An event ID, or array of ID's, e.g.
slug
- An event slug, or array of slugs, e.g.
[event-one, event-two, event-three]
- If you want to select all events EXCEPT the event with a slug of event-two, use
"not event-two"
- An event slug, or array of slugs, e.g.
allDay
- Selects only events that are set to be All Day events went set to
true
.
- Selects only events that are set to be All Day events went set to
authorId
- Selects events from specific author ID's
limit
- Supply an
int
to limit the amount of events returned
- Supply an
orderBy
- Use any of the above keys (plus
RAND()
) to order by and include theASC
orDESC
parameter in the string, e.g.orderBy: "startDate ASC"
- Use any of the above keys (plus
status
- By default,
live
is used, showing only enabled events - Can be set to
disabled
to show disabled events - Or
null
to show all events regardless of their status
- By default,
loadOccurrences
- To display only the next available recurrence in the series of a repeating event, set this to
'next'
. - To display only the next certain number of available recurrences in the series of a repeating event (e.g. the next available 3 recurrences of each event, but no more than that), set this to something like
3
. - Set this to
false
to not load event recurrences at all. Default istrue
.- When setting this to
false
, Calendar will display only the very first occurrence in the results ONLY if that same occurrence falls within the specified date range. It will NOT just show the next recurrence available, and does NOT show any events that just have recurrences within the specified date range. You will typically want to specify'next'
instead offalse
in most cases.
- When setting this to
- To display only the next available recurrence in the series of a repeating event, set this to
search: "customField:myvalue*"
- Works just like regular Craft Searching.
There's currently a known issue where searches combined with
calendar
parameter will not work. UsecalendarId
instead for now.
- Works just like regular Craft Searching.
relatedTo: event.id
- Works just like regular Craft Relations.
Methods
groupedByMonth()
- Allows you to group events by month and display a heading above each month.
groupedByWeek()
- Allows you to group events by week and display a heading above each week.
groupedByDay()
- Allows you to group events by day and display a heading above each day.
See Grouping Events by Month/Week/Day examples for more information.
Usage in Templates
{# select only all day events #}
{% set events = craft.calendar.events({
allDay: true
}) %}
{% for event in events %}
<div style="color: {{ event.calendar.color }};">
{{ event.title }}
</div>
{% endfor %}
You can also access any custom fields which you have added to events by directly calling their handle (the handle must not match any of the existing event properties). If you had a field called Event Description with a handle of eventDescription you would access it in the template like this:
{% set events = craft.calendar.events %}
{% for event in events %}
<div style="color: {{ event.calendar.color }};">
{{ event.title }}
{# You can omit the "is defined" check if you're certain that you have that field #}
{% if event.eventDescription is defined %}
{{ event.eventDescription }}
{% endif %}
</div>
{% endfor %}
Let's use a Date method to check if our event's start date is before the current Day's date
{# Print out the Y-m-d of start date if start date is before the Day date #}
{% set events = craft.calendar.events %}
{% for event in events %}
{% if event.startDate.lt(day.date) %}
{{ event.startDate.dateString }}
{% endif %}
{% endfor %}
Now let's print out the duration of the event, which is the amount of time in months, days, hours, etc from the event's start date until its end date
{#
Print out the duration string.
An example output would be "1d 5h 30m"
#}
{% set events = craft.calendar.events %}
{% for event in events %}
{{ event.duration.humanReadable }}
{% endfor %}
{#
Print out a custom message if the duration in days is 1 or more.
Please note that durations 1 month or longer will trigger 'months'
count and reset the days count back to '0' at each month interval).
#}
{% for event in events %}
{% if event.duration.days >= 1 %}
Event spans for {{ event.duration.days }} days
{% endif %}
{% endfor %}
To paginate events, use Craft's Pagination. Here's an example:
{% set eventOptions = {limit: 15} %}
{% paginate craft.calendar.events(eventOptions) as pageInfo, events %}
{% for event in events %}
<div>
{{ event.title }}
</div>
{% endfor %}
{% if pageInfo.prevUrl %}
<a href="{{ pageInfo.prevUrl }}">Previous Page</a>
{% endif %}
{% if pageInfo.nextUrl %}
<a href="{{ pageInfo.nextUrl }}">Next Page</a>
{% endif %}
To display a list of "parent" events with their recurrences paired with them (not ordered chronologically throughout all the event results), your code might look something like this:
{% set events = craft.calendar.events({
loadOccurrences: false
}) %}
{% for event in events %}
<div>
{{ event.title }} - {{ event.startDate.toDateTimeString }}
{% set occurrences = craft.calendar.events({id: event.id}) %}
{% if occurrences and occurrences|length > 1 %}
<ul>
{% for occurrence in occurrences %}
{% if loop.index0 > 0 %}
<li>
{{ occurrence.title }} - {{ occurrence.startDate.toDateTimeString }}
</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
</div>
{% endfor %}
If you want to show a list of other events, and exclude the currently viewed event, your code might look something like this:
{% set currentEventId = craft.request.segment(3) %}
<ul>
{% for event in craft.calendar.events({
id: 'not ' ~ currentEventId,
rangeStart: 'today',
rangeEnd: '1 month',
limit: 5
}) %}
<li>[{{ event.id }}] {{ event.title }} {{ event.startDate }}</li>
{% endfor %}
</ul>
Grouping Events by Month/Week/Day
If you want to group events by month/week/day, you can use this:
{% set eventOptions = {
rangeStart: "today",
rangeEnd: "2 months",
} %}
{% for month in craft.calendar.events(eventOptions).groupedByMonth() %}
<h2>Month of {{ month.startDate.format("F, Y") }}</h2>
<ul>
{% for event in month.events %}
<li>{{ event.title }} - {{ event.startDate.toDateString() }}</li>
{% endfor %}
</ul>
{% endfor %}
{% for week in craft.calendar.events(eventOptions).groupedByWeek() %}
<h2>Week of {{ week.startDate.format("F j, Y") }}</h2>
<ul>
{% for event in week.events %}
<li>{{ event.title }} - {{ event.startDate.toDateString() }}</li>
{% endfor %}
</ul>
{% endfor %}
{% for day in craft.calendar.events(eventOptions).groupedByDay() %}
<h2>Day of {{ day.startDate.format("F j, Y") }}</h2>
<ul>
{% for event in day.events %}
<li>{{ event.title }} - {{ event.startDate.toDateString() }}</li>
{% endfor %}
</ul>
{% endfor %}