I know Lindsey's answer is the accepted answer from like 4 years ago, but it's worth pointing out that it only applies if your events use postDate
for when each event starts/ends. But you don't need to do all that! Just use a custom datetime field for setting event start/end dates.
Create custom date/time fields in your entries. Then you grab your event entries on the listing page like normal but you order by your custom field:
{% set upcomingEvents = craft.entries.section('mySection').order('customStartDate')
Then control them in the loop:
{% for event in upcomingEvents if event.customStartDateField >= now %}
// event html
{% else %}
<p>There are currently no upcoming events at this time.</p>
{% endfor %}
Then on the details _entry
page, you go about it like normal; the entry
variable is auto populated for you.
There's also a more complex example on Craft Cookbook if you need something more complicated.
There are multiple reasons and benefits for using custom date fields rather than going with postDate
:
- You don't need to uncheck the box that says "Entries in this section have their own URLs". Instead, let Craft generate the entries' urls as usual.
- No wonky custom routing for what is really just a straight up typical channel of entries.
- You don't have to deal with the status; just leave it on the default "live" status and control the entry's visibility in the template based on if its start/end date is in the future or past related to the current date.
- The UX of having a custom date/time field in the entry's tab (when editing the entry) rather than off to the side is arguably far better for the user/client.
I get that the accepted answer answers the question in the title, but I found myself rethinking my approach to listing out events on a project I'm doing and realized the better way is to avoid using postDate
altogether for this instead of trying to force it. Hope it helps someone else too.