We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 4018
    • 1,131 Posts
    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?! smiley

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

    Have fun!

    Jeff
      Jeff Whitfield

      "I like my coffee hot and strong, like I like my women, hot and strong... with a spoon in them."
      • 8287
      • 12 Posts
      Jeff ... thanks a ton for this information. I really do appreciate you sharing your expertise with MODx. I will now get busy seeing how I can implement this in my site.

      Regards,
      Dennis
        • 33372
        • 1,611 Posts
        Yes - thanks for this info.

        I had given up on using getDocumentChildrenTVarOutput because I couldn’t figure out how to make it return the values with a separator (I just did a direct database query instead of using the API). I’m coming from the Etomite world, and there ain’t no widgets over there. Time to learn about widgets...

        This does seem to be a very good example for the documentation. I know that MODx has tons of features and capabilities that I’m not currently using because I don’t understand how they work. This example helps explain TVs and widgets and could be useful to more than just me.
          "Things are not what they appear to be; nor are they otherwise." - Buddha

          "Well, gee, Buddha - that wasn&#39;t very helpful..." - ZAP

          Useful MODx links: documentation | wiki | forum guidelines | bugs & requests | info you should include with your post | commercial support options
          • 18397
          • 3,250 Posts
          Jeff, would you like this simple changed merged in with Ditto?
            • 36451
            • 264 Posts
            I vote YES.
              • 4018
              • 1,131 Posts
              Quote from: Mark at Jun 15, 2006, 11:09 AM

              Jeff, would you like this simple changed merged in with Ditto?

              Absolutely! In fact, I have a few other ideas that I think you’ll like. laugh
                Jeff Whitfield

                "I like my coffee hot and strong, like I like my women, hot and strong... with a spoon in them."
                • 25663 MODX Staff
                • 12,272 Posts
                Why would you not merge it in?
                  Ryan Thrash, MODX Co-Founder
                  Follow me on Twitter at @rthrash or catch my occasional unofficial thoughts at thrash.me
                  • 8287
                  • 12 Posts
                  I would vote for the merging as well.

                  I am working to implement this configuration and modify it to what I need (see below). If anyone, more familiar with PHP programming, could quickly identify the best way of doing this, I would appreciate the help.

                  What I need is having more than one level of categories (two levels is all I really need). Then being able to list/display the categories in different ways ... such as listing businesses or services in the following way:

                  Advertising Clothing
                  Broadcast Children
                  Marketing Men
                  Outdoor Shoes
                  Print Women
                  Signs Eye Care
                  Broadcasting Contacts
                  Cable Glasses
                  Radio Physicians
                  Satelite Etc.
                  Television Etc.

                  When you click on the main category, it shows you all the businesses/services related to that (all that are listed in the subcategories). If the list is too long, you can select one of the sub-categories to narrow the search.

                  If this is possible, it would be great!

                  Thanks for the great snippet contributions.

                  Dennis
                    • 4018
                    • 1,131 Posts
                    Quote from: rthrash at Jun 15, 2006, 07:29 PM

                    Why would you not merge it in?

                    Err...probably because doing so will make you happy...

                    Now that I think about it...maybe we shouldn’t merge it in...

                    Heh heh! J/K! smiley
                      Jeff Whitfield

                      "I like my coffee hot and strong, like I like my women, hot and strong... with a spoon in them."
                      • 15987
                      • 786 Posts
                      dweitzell,
                      there a couple of ways I think you could accomplish this. If you tag each document with the outer level and the inner level you could then filter by the outer category and the inner category for finer results. The other option would be to pass in all of the subcategories when you click on the outer category. If your subcategories exist in multiple outer categories these might not work the way you want though.