Relating Elements

This page serves as an example of how to relate elements to Solspace Calendar events.

In this first example, we have a Users relation field in a Calendar field layout. This allows you to assign/relate a user to each event. At some point, you may wish to display a list of all upcoming events for that given user in your front end templates.

In the example below, we'll first get the user's username from the 2nd segment of the URL, populate a user profile page, and feed the user ID to a Calendar Events function to display upcoming events (the key here, being the relatedTo parameter):

{# Get the username #}
{% set requestedUsername = craft.app.request.getSegment(2) %}

{# Fetch that user #}
{% set user = craft.users()
    .username(requestedUsername|literal)
    .one() %}

<h2>{{ user.name }}</h2>
<p>{{ user.bio }}</p>

<h4>This User's Events</h4>
{% set events = craft.calendar.events({
    rangeStart: "24 months ago",
    rangeEnd: "99 months",
    loadOccurrences: "next",
    limit: 15,
    relatedTo: user.id
}) %}

<ul>
{% for event in events %}
    <li>{{ event.title }} / {{ event.startDate.format('l, F j, Y') }}</li>
{% else %}
    <li>No events could be found for this user.</li>
{% endfor %}
<ul>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

Relating Events to other Events

In this next example, we have set up two calendars. One is a Tournaments (tournaments) calendar, which holds all of our upcoming tournaments. The other is an Events (events) calendar, which holds sub-events happening during the tournaments.

The relationship is unidirectional, going from Tournaments to Events. Meaning, our Tournaments know which Events happen in them, but Events don't know which Tournaments they belong to.

Listing tournaments and their respective sub-events is easy:

<h2>Upcoming Tournaments</h2>

{# Getting tournaments only here #}
{% set tournaments = craft.calendar.events({
  calendar: ["tournaments"]
}) %}

{% for tournament in tournaments %}
<ul>
  <li>
    <div>
      <strong>{{ tournament.title }}</strong>:
      {{ tournament.startDate.toDateString }} - {{ tournament.endDate.toDateString }}
    </div>

    {% if tournament.tournamentEvents|length %}

    {#
      We could just iterate over tournament.tournamentEvents but
      since Calendar_EventModel contains unneeded logic which
      becomes a problem when loading thousands of events, we have
      to fetch thin Event objects using the craft.calendar.events()
      template function
    #}

    {% set events = craft.calendar.events({
      id: tournament.tournamentEvents.ids
    }) %}

    <ul>
      {% for event in events %}
      <li>
        <div>
          <strong>{{ event.title }}</strong>:
          {{ event.startDate.toDateTimeString }} ({{ event.duration }})
        </div>
      </li>
      {% endfor %}
    </ul>
    {% endif %}
  </li>
</ul>
{% endfor %}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

Listing sub-events and the tournament they belong to is a little bit more complicated:

<h2>Event list</h2>

{# Getting non-tournament events here #}
{% set events = craft.calendar.events({
  calendar: ["events"]
}) %}

{% for event in events %}
<ul>
  <li>
    <div>
      <strong>{{ event.title }}</strong>:
      {{ event.startDate.toDateString }} - {{ event.endDate.toDateString }}
    </div>

    {# We get any related tournaments here. Since two tournaments MIGHT link to the same event #}
    {% set tournaments = craft.calendar.events().relatedTo(event.id) %}
    {% if tournaments|length %}
    <ul>
      {% for tournament in tournaments %}
      <li>
        <div>
          <strong>{{ tournament.title }}</strong>:
          {{ tournament.startDate.toDateString }} ({{ tournament.duration }})
        </div>
      </li>
      {% endfor %}
    </ul>
    {% endif %}
  </li>
</ul>
{% endfor %}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Last Updated: 4/6/2021, 9:54:19 AM