« Learning Movable Type Has a New Look and Focus | Main | Installing Image::Magick on Windows »

How to List Subcategories for a Single Category

Article cross-posted at Sekimori Design.

After a few agonizing days of attempting to set up some very custom category displays for a client, we are posting the results here in the hopes it might prevent some other poor programmer from gaining the very same forehead dents we currently sport.

(Note: the following was accomplished in a MT 3.34 environment)

The objective: List subcategories for one single category in Movable Type.

The solution:

First, install Staggernation's FilterCategories plugin.

Second, set up your categories, subcategories, etc., then use this code to call them:

<MTTopLevelCategories>
<MTFilterCategories include="Category">
<ul>
<MTSubCategories>
<li>
<a href="<$MTCategoryArchiveLink $>">
<$MTCategoryLabel$>
</a>
</li>
</MTSubCategories>
</ul>
</MTFilterCategories>
</MTTopLevelCategories>

Adjust the display mechanism (ie. ul, li, etc.) as you like and there you go.

Comments (13)

The key thing with displaying (sub-)categories for a particular category is to create its context before your (sub-)categories listing code. Here Stacy's done it using MTTopLevelCategories and then filtering for a specific category.

An alternate route, one which I've used on The Style Archive, was to setup the parent category context directly using David Rayne's MTCategory plugin like so:

<MTCategory name="Category">
<ul>
<MTSubCategories>
<li>
<a href="<$MTCategoryArchiveLink$>">
<$MTCategoryLabel$>
</a>
</li>
</MTSubCategories>
</ul>
</MTCategory>

I could be wrong, but I think it's possible to achieve this without a plugin:

<ul>
<MTSubCategories>
<MTIfIsDescendant parent="Category">
<MTHasParentCategory>
<li><a href="<$MTCategoryArchiveLink$>">
<$MTCategoryLabel$></a>
</li>
</MTHasParentCategory>
<MTSubCatsRecurse>
</MTIfIsDescendant>
</MTSubCategories>
</ul>

At least, it seems to work.

While generally I would take the Route of Least Plugins, I'm going to side with Arvind on this for processing speed.

By using either MTFilterCategories or MTIfIsDescendant (both of which should probably work with the code provided), it means that the loop has to go through every category and check to see if it matches the criteria. Slooow.

By using the MTCategory plugin, however, you're setting up a category context first, meaning only one loop. Unless you only have a small list of categories, this is likely to be a much faster process.

The only change is that I'd probably through some extra tags in there, including an MTSubCatsRecurse, in case you have more than one level of SubCategory underneath the parent.

One note, and that is to be careful with where you put the MTFilterCategory tag. If it's inside of an MTSubCategory loop, such as within the typical category listing code, and in there with the MTSubCatsRecurse, then the filter will work on every iteration - which is likely to not produce what you want!

Su:

(Sort of) going a bit further with the "least plugins" idea, Tim's Gizmos includes the MTCategory context-setting functionality, along with entry, blog, comment and ping versions, plus a bunch of other stuff you'll probably end up needing at some point anyway.

boblet:

Is there any way to do this on a category archive page where the output is limited to the current category's context? Something like

<MTFilterCategories include="<$MTCategoryLabel$>">

The default tempate's category listing code used on a category archive gives me only the current top level category's subcategories and entries, but it displays all top level categories and their subcategories/entries when I view a subcategory's archive.

<MTSubCategories>
<MTSubCatIsFirst><ul></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li><h2><MTCategoryLabel></h2>
<ul>
<MTEntries>
<li><h3><a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a></h3>
<$MTEntryExcerpt$>
</li>
</MTEntries>
</ul>
<MTElse>
<li><h2><MTCategoryLabel></h2>
</MTElse>
</MTIfNonZero>
<$MTSubCatsRecurse$>
</li>
<MTSubCatIsLast></ul></MTSubCatIsLast>
</MTSubCategories>

What I'm after is the same 'everything under this category' display (well, ideally everything under this sub-category's top level ancestor).

Does that make any sense? :-)

I sure wish the documentation on categories was a bit clearer!

peace - boblet

boblet:

Figured it out

peace - boblet

If you want to just have the TOP level category name followed by a simple, linked list of subcategories, try this: (no plugins needed)

<MTTopLevelParent><$MTCategoryLabel$> <br />
<MTHasSubCategories><MTSubCategories><MTSubCatIsFirst></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount"> | <a href="<$MTCategoryArchiveLink$>"><$MTCategoryLabel$></a>
<MTElse></MTElse></MTIfNonZero><$MTSubCatsRecurse$>
<MTSubCatIsLast></ul></MTSubCatIsLast></MTSubCategories> |</MTHasSubCategories></MTTopLevelParent>

Unless I am missing something, Arvind's example appears to be more manual due to having to enter 'name=SomeCategory' every time a category is made. Those wishing to stay away from code as much as possible would stick with the example by Stacy as it's a simple cut and paste. I enjoy code, but for something as trivial as adding a category to my blog, which is done anyway when you create it in the MT interface, why create it a second time on the template(s)? In other words, where is the real gain in processing speed? ie, the MT backend? or the human factor of manually adding it in? I'm sure the contributors are well aware of this and please - correct me if I'm wrong; but maybe those new to MT may not be aware.

That was just something I picked up on and may itself be trivial. My main reason for commenting is to question if it's possible to create a DHTML similar look in that only when clicked the subcategories will appear expanding the top-level category. Possible? I notice in the Settings->Publishing->Publishing Preferences page there is this option:

"Set each template's Build Options separately"
(use this maybe in an effort to categorize dynamically?)

Can anyone clarify this or examine if it's possible?
-Patrick

Oops.. I read this before reading the other article listed here concerning collapsible categories:

http://www.learningmovabletype.com/a/000674expandable_list/

Sorry about that.
-Patrick

This works too, sans plugins (MT4):

<MTSubCategories category="Reviews">
<ul>
<MTIfNonZero tag="MTCategoryCount">
<li><a href="<$MTCategoryArchiveLink$>" <MTIfNonEmpty tag="MTCategoryDescription"> title="<$MTCategoryDescription$>"</MTIfNonEmpty>><$MTCategoryLabel$></a></li>
</MTIfNonZero>
</ul>
</MTSubCategories>

Apologies if that's a bit muddled; I got lost in a sea of &lt;s and &gt;s.

Is there a way to display a subcategory's subcategories?

Hi Addison -

It depends on the request.

If you are asking about doing it for every subcategory, then you would want to use MTSubCatsRecurse, as seen in Understanding the Category Listing Code.

If you are asking about just listing subcategories for a single subcategory, just enter that subcategory name - it doesn't matter that it is a subcategory. It's still a category.

brian:

Ok, first off here's how I have my categories and their subcategories set up:

catA
|---subCatA1
|---subCatA2
|---subCatA3
CatB
CatC
CatD
|---SubCatD1
|---SubCatD2
CatE

We are using the categories as a basic site navigation and structure, I need to figure out how to show the correct category for an entry so the user can always see where they are in our system.

Here's what I would like to do:

On the main page, the navigation should show only the main cats A, B, C, D, E. That's easy just using TopLevelCategories.
catA
CatB
CatC
CatD
CatE


On a category list page I would like the navigation to display the Main cats, and the subcats for only the top level category selected. For example, I click on Cat A from the main nav, it would appear like this:

catA
|---subCatA1
|---subCatA2
|---subCatA3
CatB
CatC
CatD
CatE

Now, if I am in a subcategory of that main category (say viewing an entry posted to SubCatA1) I would like it to appear like this:
catA
|---subCatA1
|---subCatA2
|---subCatA3
CatB
CatC
CatD
CatE

I am banging my head against the wall with this (And I also have the dents to prove it!). I would like to be able to do it without hard coding the categories into the templates if possible so I don't have to maintain a template for each category. I also tried using MTFilterCategories, but I couldn't pass in an MT variable that I set based on where the user is currently.

Anyone, please help!
TIA,
Brian

Post a comment

(If you haven't left a comment here before, your comment may need to be approved before will appear on the entry. Thanks for waiting.)