Answers.Body: <p>You could do something like this:</p>
  
  <pre class="lang-twig prettyprint-override"><code>{# Fetch all entries in postDate and category/structure order #}
  {%  set entries = craft.entries().section('companies').order('dateCreated DESC').all() | multisort(e =&gt; e.yourCategoryField.one().lft ?? 1000) %}
  
  {# Group entries by categories and set a group name for non-categorised one #}
  {% set allEntriesByCat = entries|group(e =&gt; e.yourCategoryField[0] ?? 'The non categorised one') %}
  
      {% for groupName, entries in allEntriesByCat  %}
          &lt;h1 class="text-2xl"&gt;{{ groupName }}&lt;/h1&gt;
          &lt;hr&gt;
          {% for entry in entries %}
              {{ entry.title }}&lt;br&gt;
          {% endfor %}
      {% endfor %}
  
  {% endblock %}
  </code></pre>
  
  <p>Change <code>yourCategoryField</code> to your own field handle, of course. The Order of your sponsorship levels (<code>{{ groupName }}</code>) is the one you will define by drag/dropping in your Control Panel → Categories.</p>
  
  <p>Note that this won't show an empty sponsorship level if there is no company attached to it.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-27T22:59:04.637Z
Answers.Text: Thanks. That's what I was looking for. If I don't need to show the group name as a header, can I eliminate one of the for loops?
Answers.UserDisplayName: artmem
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-28T00:43:51.880Z
Answers.Text: no, you'd need both loop but just don't echo `{{ groupName }}`. It's all on one query so the two loops don't really *cost* anything
Answers.UserDisplayName: Oli
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-28T04:32:30.947Z
Answers.Text: Ok, great. Thanks!
Answers.UserDisplayName: artmem
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-27T22:16:39.000Z
Answers.LastActivityDate: 2020-02-28T14:14:32.437Z
Answers.LastEditDate: 2020-02-28T14:14:32.437Z
Answers.UserDisplayName: Oli
Body: <p>I have a channel that is essentially a list of companies participating in an event. </p>
  
  <p>Within that channel is a category group of sponsorship levels.</p>
  
  <p>Companies that are sponsors are assigned a category. Companies that are just participants are not categorized.</p>
  
  <p>I need to output a list of companies beginning with the categorized entries, and then the rest of the uncategorized entries.</p>
  
  <p>The code I'm using below outputs the categorized list, but then I'm doing another loop for all companies (not just uncategorized).</p>
  
  <p>Is there a better way, where I can exclude the categorized companies from the second loop (or include the uncategorized companies in the first loop?</p>
  
  <pre><code>{% set allCompanies = shuffle(craft.entries.section('companies').all()) %}
  {% set sponsorCats = craft.categories().group('sponsors').relatedTo(allCompanies) %}
  
  {# Loop the categories #}
  {% for category in sponsorCats.all() %}
  
      {# Get and loop through entries related to this cat #}
      {% set sponsors = craft.entries.relatedTo(category) %}
  
      {% for entry in sponsors.all() %}
          entry details
      {% endfor %}
  {% endfor %}
  
  {% for entry in allCompanies %}
      entry details
  {% endfor %}
  </code></pre>
  
Tags: <entries><categories>
Title: list entries by category, including uncategorized entries
ThreadText: # list entries by category, including uncategorized entries
  
  (Asked by: username_0 on 2020-02-27)
  
  I have a channel that is essentially a list of companies participating in an event.
  
  Within that channel is a category group of sponsorship levels.
  
  Companies that are sponsors are assigned a category. Companies that are just participants are not categorized.
  
  I need to output a list of companies beginning with the categorized entries, and then the rest of the uncategorized entries.
  
  The code I'm using below outputs the categorized list, but then I'm doing another loop for all companies (not just uncategorized).
  
  Is there a better way, where I can exclude the categorized companies from the second loop (or include the uncategorized companies in the first loop?
  
  ```
  {% set allCompanies = shuffle(craft.entries.section('companies').all()) %}
  {% set sponsorCats = craft.categories().group('sponsors').relatedTo(allCompanies) %}
  
  {# Loop the categories #}
  {% for category in sponsorCats.all() %}
  
      {# Get and loop through entries related to this cat #}
      {% set sponsors = craft.entries.relatedTo(category) %}
  
      {% for entry in sponsors.all() %}
          entry details
      {% endfor %}
  {% endfor %}
  
  {% for entry in allCompanies %}
      entry details
  {% endfor %}
  
  ```
  
  **Tags:** entries, categories
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2020-02-27. Score: 3 | Accepted answer
  
  You could do something like this:
  
  ```twig
  {# Fetch all entries in postDate and category/structure order #}
  {%  set entries = craft.entries().section('companies').order('dateCreated DESC').all() | multisort(e => e.yourCategoryField.one().lft ?? 1000) %}
  
  {# Group entries by categories and set a group name for non-categorised one #}
  {% set allEntriesByCat = entries|group(e => e.yourCategoryField[0] ?? 'The non categorised one') %}
  
      {% for groupName, entries in allEntriesByCat  %}
          <h1 class="text-2xl">{{ groupName }}</h1>
          <hr>
          {% for entry in entries %}
              {{ entry.title }}<br>
          {% endfor %}
      {% endfor %}
  
  {% endblock %}
  
  ```
  
  Change `yourCategoryField` to your own field handle, of course. The Order of your sponsorship levels (`{{ groupName }}`) is the one you will define by drag/dropping in your Control Panel → Categories.
  
  Note that this won't show an empty sponsorship level if there is no company attached to it.
  
  > **Comments:**
  > **username_0**: Thanks. That's what I was looking for. If I don't need to show the group name as a header, can I eliminate one of the for loops?  
  > **username_1**: no, you'd need both loop but just don't echo `{{ groupName }}`. It's all on one query so the two loops don't really *cost* anything  
  > **username_0**: Ok, great. Thanks!  
  
  ---
  
  