« 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 (7)

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>

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.)