1

I'm working on creating a simple calendar based on only native Craft fields. While coding this, I'm having a hard time getting the pagination to work properly.

The calendar currently lists all upcoming events this current month. Next/Previous should then paginate the calendar 1 full month forward/backward (not 1 month backwards from todays date, but all entries in the next/previous month).

According to Brandon, paginate.prevUrl/nextUrl won't map to specific date-based starting points. So, how do I tackle this problem then?

Here's my current code:

<div class="row">
    <div class="small-12 medium-12 large-12 columns">
        <div class="widget_event single_widget box_shadow">
            <h3>Hva skjer i Filadelfia</h3>

            {% set startDateTime = now|date_modify('0:00')|date('c') %}
            {% set endDateTime = now|date_modify('first day of next month 4:00')|date('c') %}

            {% set startDateParam = 'and, >= ' ~ startDateTime ~ ', < ' ~ endDateTime %}

            {% set events = craft.entries.section('calendar').limit('15').startDate(startDateParam).order('startDate asc') %}

{% for event in events %}
    <div class="event_list">
        <div class="single_event">

            <div class="date_left">
                <p class="date">{{ event.startDate | date("d") }}.</p>
                <p class="day">{{ event.startDate | date("M") }}</p>
            </div>

            <div class="title_middle">
                <p class="title">{{ event.title }}</p>
                <p class="desc">{{ event.body | hacksaw(words='75', allow='<b><strong><i><em>') }}</p>
            </div>

            <div class="time">{{ event.startDate | date("H:i") }}</div>

        </div>
    </div>
{% endfor %}


{% paginate craft.entries.section('calendar').limit(15) as pageEvents %}
    {% for month, entries in pageEvents | group("postDate | date('F')") %}
        <div class="event_nav text-center">
            <span class="left left_arrow">{% if paginate.prevUrl %}<a href="{{ paginate.prevUrl }}">Previous Month</a>{% endif %}</span>
            <span class="right right_arrow">{% if paginate.nextUrl %}<a href="{{ paginate.nextUrl }}">Next Month</a>{% endif %}</span>
        </div>
    {% endfor %}
{% endpaginate %}

        </div>
    </div>
</div>
1

Instead of using pagination you might want to look into setting up a dynamic route in the format "calendar/[year]/[month]". Adding 'year' and 'month' tags to your route will essentially pass those values as named variables to your template, which you can use to retrieve and display entries, as well as generate navigation to next/previous month's events. If you want the uri '/calendar' (without the 'year/month' uri segments) to link to the current months events you can test for the existence of the 'year' and 'month' variables, and if not defined, set the start month to the first day of the current month.

{% if year is defined and month is defined %}
    {% set startMonth = year ~ '-' ~ month ~ '-' ~ 1 %}
{% else %}
    {% set startMonth = now|date_modify("first day of this month") %}
{% endif %}
{% set nextMonth = startMonth|date_modify('+1 month')) %}
{% set previousMonth = startMonth|date_modify('-1 month')) %}

{% set entries = craft.entries.section('calendar').postDate('and', '>= ' ~ startMonth, '< ' ~ nextMonth %}

{% for entry in entries %}
    {{ entry.title }}
    ...
{% endfor %}

<div class="pagination">
    <a href="{{ 'events/' ~ nextMonth|date("Y/n") }}">next month</a>
    <a href="{{ 'events/' ~ previousMonth|date("Y/n") }} ">previous month</a>
</div>

If required, within any month you could also use a pagination tag if you needed to limit the number of events displayed on any one page to 15.

For additional examples see these answers, here and here.

  • Thanks for the example. I've never used Routes before. How would my actual route look like when the calendar in question is an include that is part of my homepage? Would it be "calendar/year/month" ? Which template should I specify it to load then? Since it's an include, and not a template in the way I think of a template? – Filadelfia Jun 26 '15 at 7:30
  • Also, curious if it's possible to actually display the month name when paginating backward/forward? So instead of saying "Previous Month", it would say "May". BTW: your current code works perfectly, except for the previous/next links, because of the Route part not being correct set up. – Filadelfia Jun 26 '15 at 8:02
  • Sorry, I think the month number without the leading zero is represented by 'n' instead of 'm'. I'll update the answer. See the php date docs for more info. To output the month name, I believe you can use 'F': <a href="{{ 'events/' ~ nextMonth|date("Y/n") }}">{{ nextMonth|date("F") }}</a> – Douglas McDonald Jun 27 '15 at 16:42
  • Regarding the include question — if your looking to include events on the homepage, you might want to consider using ajax to load the calendar (to keep the uri's clean). Or perhaps consider having the "hompage" calendar (which shows the current month's events) link to the full calendar for previous/future events. Otherwise, if you want to incorporate routes with the homepage you would probably want to drop the 'calendar' segment of the route and just use [year]/[month] as your route, and specify the homepage template as the route template. The calendar could still be a template include. – Douglas McDonald Jun 27 '15 at 16:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.