Skip to main content

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 or 5 years ago, etc to avoid running into potential performance issues or quirkiness. A date range of 2023-01-01 to 2023-02-15 would show all events and their recurrences that occur between January 1, 2023 to February 15, 2023. A start range of 2023-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 or 2023-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 and rangeEnd parameters if results are not reliable enough when using with recurring events):
      • startsAfter: "now"
      • startsAfterOrAt: "now"
      • startsBefore: "now"
      • startsBeforeOrAt: "now"
  • 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 of 2023-01-01 to 2023-02-15 would show all events and their recurrences that occur between January 1, 2023 to February 15, 2023. An end range of 2023-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 or 2023-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 and rangeEnd parameters if results are not reliable enough when using with recurring events):
      • endsAfterOrAt: "now"
      • endsAfter: "tomorrow"
      • endsBefore: "now"
      • endsBeforeOrAt: "now"
  • 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
  • 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"]
  • 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"
  • 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"
  • allDay
    • Selects only events that are set to be All Day events went set to true.
  • authorId
    • Selects events from specific author ID's
  • limit
    • Supply an int to limit the amount of events returned
  • orderBy
    • Use any of the above keys (plus RAND()) to order by and include the ASC or DESC parameter in the string, e.g. orderBy: "startDate ASC"
  • 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
  • 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 is true.
      • 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 of false in most cases.
  • search: "customField:myvalue*"
    • Works just like regular Craft Searching.

      There's currently a known issue where searches combined with calendar parameter will not work. Use calendarId instead for now.

  • relatedTo: event.id

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 %}