Ok...I’m gonna put down the basics on tagging documents with multiple categories.
First and foremost, you gotta have a template variable assigned that will hold the values for the chosen categories for each document. This can be either a textbox or a listmenu...it’s your choice on how you wish to implement it. There’s alot of different ways to implement it and, for me, since the application of it was to be a blog, I choose to use a simple textbox. This way I could simply type in simple keyword values for each document as a comma separated list. Comma separated values are the easiest to implement but of course you can use something else to separate your values with.
In the case of a listmenu, you’ll need to use a multi-select menu if you want to be able to tag a document with multiple categories. You can populate the list using @ bindings but to keep it simple you can simply type in a static list of categories for the "Input Option Values". A list of values might look like this:
category1||category2||category3
From there, you would set the Widget option of the template variable to Delimited List and set the Delimiter to a comma or whatever delimiter you wish to use. This ensures that when a document is saved that the value for the template variable is saved with the correct delimited value as well. Since you probably don’t want any of your documents to have an empty value for your category TV, you’ll probably want to assign a default value.
Now all you need to do is create an unpublished folder and create some documents using the template for which your template variable is assigned to. Create a few published test documents and assign them some categories. From there, we can now create a snippet that will parse out a list of the categories assigned to your documents. We’ll need the document ID of the folder holding the categorized documents as well as the name of the template variable used to hold the category names. The snippet below is a relatively simple example of how you can parse out the category names from the documents and output a simple list of links that simply pass a specific URL variable to a given page for further filtering:
// Snippet for creating a list of category links
// ID of folder holding documents to categorize
$folderid = 7;
// Name of template variable used to hold category names
$cattv = 'BlogCategories';
// Delimiter used to separate category names
$catDelimiter = ',';
// Name for URL variable to use in links
$catvar = 'cat';
// ID of the document used to filter the category
$filterid = 5;
$allCats = $modx->getDocumentChildrenTVarOutput($folderid,array($cattv),1);
$countAllCats = count($allCats);
$arrTagsOutput = array();
for($p = 0; $p < $countAllCats; $p++){
$arrCats = explode($catDelimiter,$allCats[$p]['BlogCategories']);
$arrCatsOutput = array_merge($arrCatsOutput, $arrCats);
}
$arrCatsOutput = array_unique($arrCatsOutput);
sort($arrCatsOutput);
$countCatsOutput = count($arrCatsOutput);
for($q = 0; $q < $countCatsOutput; $q++){
$catLinks .= "<li><a href=\"[~".$filterid."~]?".$catvar."=".$arrCatsOutput[$q]."\">".$arrCatsOutput[$q]."</a></li>";
}
return "<ul>".$catLinks."</ul>";
The parameters at the top are pretty self explanatory. The good part about this approach is that the list only contains the categories for which the documents are using. We certainly don’t want to display a category for which no document is assigned so...why even list it?
Now then...where do you go from here? Well, that depends on what your goal is. You can use the page assigned to the $filterid variable to create an additional snippet that will use the URL variable passed to filter and display your documents. It’s pretty much a matter of using a similar approach to the snippet above by using the getDocumentChildrenTVarOutput call to loop through the value of the template variable in your documents to check for the existence of the URL variable in the value. Depending on your use, you might want to create this snippet from scratch if you need something highly customized. However, it’s much easier to use an existing snippet like the NewsLister or Ditto. I choose to use Ditto. And, believe it or not, the changes required are quite simple. In the snippet code for Ditto, look for the following around lines 297 to 300:
// ---------------------------------------------------
// Tagging Parameters
// ---------------------------------------------------
if (isset($tags) && !empty($tags) && isset($tagData)) {
And change it to this:
// ---------------------------------------------------
// Tagging Parameters
// ---------------------------------------------------
if(isset($tagurl)) {
if(isset($_GET[$tagurl])){
$tags = $_GET[$tagurl];
}
}
if (isset($tags) && !empty($tags) && isset($tagData)) {
You can see where I’m going with this. I added a $tagurl variable so I can pass the name of my URL variable to Ditto and assign it to the $tags variable for filtering. A typical Ditto call using tags might now look like this:
[!Ditto? &startID=`7` &tpl=`BlogSummaryPost` &hiddenTVs=`BlogCategories` &tagData=`tvBlogCategories` &tagDelimiter=`,` &tagurl=`cat` &tagMode=`onlyTags`!]
No muss, no fuss...and I can use Ditto’s templating capabilities to create the output I’m looking for. The combination of Ditto and the category links snippet is all I need to create a way of assigning, displaying, and filtering documents into multiple categories. How cool is that?!
Hmm...now that I’ve written this, perhaps a full-blown tutorial on the blog is in order. Let me know if this explains everything. I might have missed something.
Have fun!
Jeff