ExpressionEngine Tip: Highlight Only Active Categories in a Category List

EE Tip: Show all Categories, only highlighting active ones!

Perhaps you’ve been here before: you want to show all of the categories in a particular ExpressionEngine category group, while also highlighting only those categories to which a particular entry belongs.

This is not something EE’s category tags can do natively, so I set out to find a way. I’ll show you what I discovered in this short tutorial.

Last things first: the final result

In case the concept is still abstract, here is a screenshot of the final result:

A list of all categories, with active ones checked

What you see is a portion of a Safecracker form for editing a single entry. I wanted to let the end user see all of the category options, as well as which categories were already selected for the current entry. A checkbox field seemed like a logical choice.

You’ll notice that some of the checkboxes are checked, and that there are no duplicate categories. I know…like magic.

How it’s done

In this example, I’m using an embedded template, but that may not be necessary for everyone. In your parent template, place the following code:

<h2>Type of Venue</h2>
<div class="cats">{embed="includes/fetch_cats" cat_group="1" entry_id="{entry_id}"}</div>

Then, in your embedded template (includes/fetch_cats in this example), place the following code:

<?php
// get all categories in the specified group
$all_cats = $this->EE->db->query ( "SELECT cat_id, cat_name FROM exp_categories WHERE group_id = '{embed:cat_group}' ORDER BY cat_name" );

// loop through each cat returned, marking a box checked if the current entry is in that cat
foreach ( $all_cats->result() as $row ) {
   $venue_cats = $this->EE->db->query ( "SELECT cat_id AS venue_cat_id FROM exp_category_posts WHERE entry_id='{embed:entry_id}' AND cat_id = '" . $row->cat_id . "'" );
   if ( $venue_cats->num_rows() ) {
      echo '<label><input checked="checked" type="checkbox" name="category[]" value="' . $row->cat_id . '" /> ' . $row->cat_name . '</label>';
   } else {
      echo '<label><input type="checkbox" name="category[]" value="' . $row->cat_id . '" /> ' . $row->cat_name . '</label>';
   }
} ?> 

Be sure that your embedded template has PHP enabled on Output.

That’s all there is to it. The nice thing about using an embedded template is that it’s very modular; you can pass any category group ID  and entry ID to it and it will return the expected categories.

This article was written by Ryan.

Ryan is the lead web developer at 3 Roads Media. He has been coding websites since 1996.

Ryan

5 comments

  • David McCormick

    May 3, 2012

    Amazing – thanks very much, Ryan; I’d never have got there on my own.

    It might be worth explicitly wrapping the embed code with php tags (because slow-to-catch-on types like me could end up stroking their chin and wondering why there’s loads of code showing up on their site).

    Reply
    • Ryan

      May 3, 2012

      Hey David,

      I’m glad the tutorial helped! Good suggestion — I wrapped the embed code in php tags as you suggested.

      Reply
  • Olivier

    December 4, 2012

    Hi,
    I am glad I found this, your bits of code is exactly what I am desperatly trying to achieve.
    Unfortunately, the categories appear, but all selected.
    Any idea what might be wrong?
    Thanks in advance

    Reply
  • Olivier

    December 4, 2012

    Nevermind, I found the problem: the {embed} was outside of the channel:entries so the {entry_id} wasn’t taken in consideration. Stupid.
    Thanks a lot for the tutorial, it saved my day ^__^

    Reply
    • Ryan

      December 4, 2012

      Hey Olivier, I’m glad you found the problem and that you found the tutorial helpful. Awesome!

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Notify me of follow-up comments via e-mail (you can also subscribe without commenting).

Denver web design by 3 Roads Media All materials © 2013