1

I'm creating a dynamic side navigation where pages can choose which sidebar it wants to use. This is selected by an entries field called 'sidebar' - called in line 2.

To create this I've made a structure called 'Sidebars' with an entry for each sidebar type. Each Sidebars entry has an entries field in it which can select any number of pages.

I've got it fully working, but it's giving me deprecation errors.

Here's the working (but deprecated code on line 4): (lines 5-12 figure out whether the path includes 'whats-on' or 'who-we-are' and adds them to the path to the entry if needed).

<div>
  {% set sidebarChoice = entry.sidebar.one() %}
  {% for rel in sidebarChoice %}
    {% for sidebarEntry in rel %}
      {% set myEntryQueryUrl = sidebarEntry.url %}
      {% if 'whats-on' in myEntryQueryUrl %}
        {% set myEntryQueryPath = '/whats-on/' %}
      {% elseif 'who-we-are' in myEntryQueryUrl %}
        {% set myEntryQueryPath = '/who-we-are/' %}
      {% else %}
        {% set myEntryQueryPath = '/' %}
      {% endif %}

      <div>
        <h3>{{ sidebarEntry.title }}</h3>
        <a href="{{ myEntryQueryPath }}{{ sidebarEntry.slug}}">
        <p class="smallcontentblocks-text">{{ sidebarEntry.title }} text</p>
        </a>
      </div>

    {% endfor %}
  {% endfor %}
</div>
2
  • What deprecation error are you seeing? Commented Aug 21, 2020 at 1:09
  • I'm getting this: Looping through element queries directly has been deprecated. Use the all() function to fetch the query results before looping over them. And the error is on the line {% for sidebarEntry in rel %} But when I try {% for sidebarEntry in rel.all() %} I get the Twig Runtime Error page with the notice: Impossible to invoke a method ("all") on a string variable.
    – Jonathan
    Commented Aug 21, 2020 at 10:34

2 Answers 2

1

You don't mention what your related entries field handle is, but remember that calling any related element (entries/assets/categories/users/tags) will require a .all() (or .one() or .ids() or one of the other query-executing methods) unless the related elements are eager-loaded. With that in mind I can't see anywhere in your code where you're executing a call to fetch the related entries from sidebarChoice, and you also seem to have a redundant inner loop. With eager-loading it might look like this:

<div>
  {% set sidebarChoice = entry.sidebar.with(['sidebar.yourRelatedEntriesHandle']).one() %}
  {% for sidebarEntry in sidebarChoice.yourRelatedEntriesHandle %}
      {% set myEntryQueryUrl = sidebarEntry.url %}
      {% if 'whats-on' in myEntryQueryUrl %}
        {% set myEntryQueryPath = '/whats-on/' %}
      {% elseif 'who-we-are' in myEntryQueryUrl %}
        {% set myEntryQueryPath = '/who-we-are/' %}
      {% else %}
        {% set myEntryQueryPath = '/' %}
      {% endif %}

      <div>
        <h3>{{ sidebarEntry.title }}</h3>
        <a href="{{ myEntryQueryPath }}{{ sidebarEntry.slug}}">
          <p class="smallcontentblocks-text">{{ sidebarEntry.title }} text</p>
        </a>
      </div>
  {% endfor %}
</div>
1
  • Thanks, the related entries field handle is sidebarTitle.
    – Jonathan
    Commented Sep 2, 2020 at 15:12
0

Thanks, the related entries field handle is sidebarTitle.

The first part of the above cleared the errors with an additional .all():

<div>
{% set sidebarChoice = entry.sidebar.with(['sidebar.sidebarTitle']).one() %}
     {% for sidebarEntry in sidebarChoice.sidebarTitle.all() %}
     {% set myEntryQueryUrl = sidebarEntry.url %}
     {% if 'whats-on' in myEntryQueryUrl %}
     {% set myEntryQueryPath = '/whats-on/' %}
     {% elseif 'who-we-are' in myEntryQueryUrl %}
     {% set myEntryQueryPath = '/who-we-are/' %}
     {% else %}
     {% set myEntryQueryPath = '/' %}
     {% endif %}

 <div>
    <h3>{{ sidebarEntry.title }}</h3>
    <a href="{{ myEntryQueryPath }}{{ sidebarEntry.slug}}">
      <p class="smallcontentblocks-text">{{ sidebarEntry.title }} text</p>
    </a>
  </div>
{% endfor %}
1
  • If you eager load correctly, you won't need the .all() in {% for sidebarEntry in sidebarChoice.sidebarTitle.all() %} (that's the whole point of eager loading, to prevent extra queries). Double check your eager-loading syntax - it's possible it should just be .with(['sidebarTitle']. Commented Sep 4, 2020 at 14:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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