Recently, I've been working on an Umbraco website for a client
that required several blogs, but each blog needed to have it's own
set of tags and the Tag Cloud needed to be compartmentalised.
NOTE: The code
described below didn't quite work out as I'd hoped with further
testing, so I went back to the drawing board. Take a look at
the post Blog Categories
in Blog4Umbraco - Take Two for a much cleaner and more
transparent solution to the problem with flexible Tag Groups.
Problem Number 1: Tag Clouds in Umbraco are
non-discriminatory
If you have more than one blog in Umbraco, go take a look at
your Tag Cloud. You will notice that all tags are listed, not
just those for a specific blog. Worse, even Documents that
have a Tag Data-typed attribute will contribute to the Tag Cloud,
regardless of whether they are a Blog Post document or not.
As a result, clicking on one of those tags will not
necessarily result in listing blog posts.
Adding a Tag Category to an blog
Adding a category is as simple as adding another attribute to
the Blog Document Type. Here's my settings:
Adding a Category
attribute to the Blog Document Type
To apply the category, go to the root document of your blog and
update the field, save and publish. Done. Now what?
It's all about the Tags
First, some background: The Umbraco Tag datatype allows
the administrator to set up tags for document types, which can then
be used in various ways - as a Tag Cloud, to loosely associate
related documents (allowing the developer to list those documents
automatically on an Article page, for example), etc.
By default, the Tags Data Type uses a Tag Group named,
surprisingly enough, "Default". However it's possible to
create a new Data Type - call it say "Event Tags" - and specify a
new Group - in this case, "Events":

Creating a new Event
Tags Datatype - Notice the Tag group that can be specified once you
choose the Tags control.
The advantages of doing this mean that you could have a tag
cloud for a specific group of articles - essentially creating an
article Category... Exactly what we want for our multiple blogs
scenario.
Note: For this
solution, creating a new Tag Data Type is not actually necessary.
This step is one of the paths I originally took trying to
resolve this issue, and serves as background information to what we
are trying to do. However I quickly realised that this wasn't going
to serve my needs at all.
Using a non-standard Tag Group in Blog4Umbraco
Ok, so now we have a category associated with a blog, and we
have a grouping for a set of tags. But how do we make sure
that tagging an article in a Blog Entry uses the correct Tag
Group?
As it turns out, this isn't so straightforward. We can't
just change the Blog Post Document Type to use our new Event Tags
Data Type, as all blog entries, on all blogs, must by necessity use
the Blog Post Document Type. If you try to create a new
Document Type based on the Blog Post one, Blog 4 Umbraco simply
refuses to work with it.
After some investigation, I decided that the best approach was
to implement some Event Handling Code. The beauty of this
approach is that you are actually able to roll your own Library -
there's no need to modify any existing source code. So here
goes:
Writing an Event Handler
We want to write an Event Handler. In order to make
sure our event handler is registered, we need to derive from the
Umbraco ApplicationBase class, and register our handlers in
the Constructor:
public class SetTags : ApplicationBase
{
public SetTags()
{
Document.AfterSave += Document_AfterSave;
}
void Document_AfterSave(Document sender, umbraco.cms.businesslogic.SaveEventArgs e)
{
FixTags(sender);
}
}
Handling the Document.AfterSave Event
The core of this solution is to examine the Blog Post document,
retrieve a list of Tags, and any tags that don't currently have a
Group that matches the category attrbute we applied to the Blog
earlier need to be removed and replaced with new ones associated
with the desired group. For this I have the following
Method:
private void FixTags(Document sender)
{
if (sender.ContentType.Alias == "BlogPost")
{
if (sender.Parent != null) //If top of tree, something is wrong. Skip.
{// Get the Blog category.
// We want to remove any tags on the document that aren't associated with the Blog category.
string category = BlogLibrary.GetValueRecursively(sender.Id, "category").ToString();
if (string.IsNullOrEmpty(category))
// No point continuing - we'll use the default tag group.
return;
StringBuilder tags = new StringBuilder();
foreach (var t in umbraco.editorControls.tags.library.GetTagsFromNodeAsITags(sender.Id))
{
if (t.Group != category)
{
if (tags.Length > 0)
tags.Append(",");
tags.Append(t.TagCaption);
umbraco.editorControls.tags.library.RemoveTagFromNode(sender.Id, t.TagCaption, t.Group);
}
}
umbraco.editorControls.tags.library.addTagsToNode(sender.Id, tags.ToString(), category);
}
}
}
Some notes on this code:
- Line #9: The BlogLibrary.GetValueRecursively
method is a refactoring of the private method in the Autoping Event
Handler class in the Blog4Umbraco dll. All I've done is
extract it into a public static method in the BlogLibrary class,
and switch the parameters (mainly because it makes more sense to me
to have the Node Id as the first parameter). I've also
changed the return value to an object type instead of string.
For reference, I include the code for that method here:
public static object GetValueRecursively(int nodeId, string alias)
{
Document n = new Document(nodeId);
Property p = n.getProperty(alias);
if (p != null && !string.IsNullOrEmpty(p.Value.ToString()))
return p.Value;
else if (n.Level > 1)
return GetValueRecursively(n.Parent.Id, alias);
return string.Empty;
}
- Lines 23 & 26: The
umbraco.editorControls.tags.library exposes all the tag
manipulation methods we need. We retrieve the list of tags
associated with this node, and any node that doesn't have a group
matching the Blog Category gets removed and added to the new Tag
list. Then after going through all the tags, we add back the
new Tags with the Blog category as their Tag Group.
Compile your dll, copy it to the bin directory of your Umbraco
installation, and try it out. Whenever you tag a Blog Post
and save the document, all tags will re-added with the new Tag
Group:

The Tags
Database Table after the test Tag has been added with the Events
Group.
Of course, you'll be wanting to go and
tweak your Tag Cloud xslt code to take advantage of the Blog
Category and Tag Groups next... I'll cover that in another Blog
Entry...