1

I have an Events section on my site, and to display upcoming and passed events (entries with a status of pending or expired) I manually set the entry in the template:

Where the URL is /events/my-event-title

{% set entry = craft.entries({
    section: 'Events',
    slug: craft.app.request.segment(2),
    status: ['live','pending','expired']
}).one %}

<h1>{{ entry.title }}</h1>

{{ entry.body }}

This works great except when I go to publish a new Event and use the Live Preview. Since the new entry doesn't have a slug yet, the craft.app.request.segment(2) variable returns null, and so entry returns the last-published Event entry instead. So all of my template variables are pre-populated with a different entry's content.

How do I set this up so my Live Preview displays blank until I enter content?

1

If your “event” Entry's Section settings define a URI and a template path, Craft will take care of defining entry in the template. No need to look it up by segment!

Generally speaking, this will “just work” for Live Preview, as well.

👉 I'd recommend setting the Event Section's Template to _events/event, and creating templates/_events/event.twig in your project folder. Then, entry will be automatically available when the template is rendered, either from a front-end request, or via Live Preview.

I can't speak exactly to the internals of Live Preview—but I can say that it side-steps the normal routing by laterally POSTing the updated content to a Craft Controller that independently resolves and renders the template. That said, once it starts rendering the template, it's almost exactly the same context you'll get when the Entry is live, and requested via its normal URL.

👆 Using an underscore in the template's path will make sure the template is not directly accessible, and is only rendered during a request that Craft has determined matches an Element (in your case, the event Entry), or via the Live Preview controller. Read more about how Craft routes requests, here.

  • If the entry has a pending or expired status, as my upcoming and passed events entries do, then Craft will not recognize the native entry variable in the template. – kmgdev Jan 5 at 22:01
  • I've just tested this with an Entry in the pending state, and Live Preview works as expected… can you confirm your Template path and Entry URI Format, as they appear your Section's settings, and post the contents of the template you expect to render the Entry? – August Miller Jan 6 at 2:24
  • Also worth noting—pending and expired entries are not accessible via the front-end, when using Craft's normal routing system—but Live Preview will work just fine (as will a URL created with the "Share" button at the top of the Entry edit page)… – August Miller Jan 6 at 2:24
  • Yes, I know pending and expired entries aren't accessible via the front-end, that's the whole reason I'm asking this question. Having Live Preview working doesn't do me any good if the front-end template does't also work. I need BOTH live preview AND the front-end to work for pending and expired entries. – kmgdev Jan 6 at 21:02
  • It sounds like the Pending and Expired fields are being used for something they're not well-suited for… if you just need your Events to have dates, I'd recommend using a custom field—you can still sort and filter based on custom date fields (like you can with postDate and expiryDate, and you won't have to subvert the automatic behaviors. – August Miller Jan 6 at 22:19
1

I updated my template to conditionally set the {{ entry }} variable depending on if the request is a live preview or not.

{% if not craft.app.request.isLivePreview() %}
    {% set entry = craft.entries({
        section: 'Events',
        slug: craft.app.request.segment(2),
        status: ['live','pending','expired']
    }).one %}
{% endif %}


<h1>{{ entry.title }}</h1>
{{ entry.body }}

So if it's a Live Preview request, tell Craft to use its native dynamic {{ entry }} variable, which will work in Live Preview no matter what the entry's status is.

But if the request is not a live preview, we need to explicitly tell the template what entry we're trying to access, so we set the craft.entries variable.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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