Umbraco 7

Using Tags to create new pages

Using Eventhandlers and Tag property types to create a new page. 

Photo by Sergi Viladesau on Unsplash

Background

In Umbraco there is a data type that allows you to set tags to your content. In the official Umbraco documentation tags are described as the following:

Tags - A textbox that allows you to use multiple tags on a Document Type. You can specify a Tag Group for this data type, in case you need to use Tags on different sections of your site (i.e News, Article, Events).

And they look something like this when used:

Screenshot of tags data type

You can then display these tags to the frontend if you want. In this blog I'm going to explain how I had a requirement to create a 'Topics' page that displayed all content that has the same tag set.

This could be used in a Tag Cloud or something similar. What I needed though was for the Topics page to be automatically created when a Tag was applied to a page and published.

I will explain how I did this now.

The Setup

As I mentioned, you need to have place a Property Editor with the type Tag on your Document Type.

Then we need to subscribe to the on publish event. What does this do? It allows us to do custom actions when a user clicks on the Save and Publish button.

In this instance, when the user clicks Save and Publish, we will check to see if any tags have been set, we will then check to see if a page has been created with the name of the tag e.g. if a tag is set as Umbraco we check to see if there is a topic page already created called Umbraco. If there is, then we do nothing, if there isn't then we create and publish the page.

How do we do this?

Note: This example is in Umbraco 7

Firstly, create an eventHandler class. In my example, the file is saved within its own folder called EventHandlers and the file is called Global.cs. You can call it whatever you want.

I won't go in to all the details of how to setup this file because the Umbraco Documentation does a great job at that.

You can hook in to loads of different options, when something is trashed - put in to the recycle bin, when something is saved, when something is being saved, but what I used was on publish.

This is also the example that the documentation uses which is handy.

private void ContentService_Publishing(IPublishingStrategy sender, PublishEventArgs<IContent> e)
        {
            foreach (IContent contentItem in e.PublishedEntities
             .Where(c => c.ContentType.Alias == OpinionContent.ModelTypeAlias || 
             c.ContentType.Alias == VideoItem.ModelTypeAlias || 
             c.ContentType.Alias == WebinarContent.ModelTypeAlias ||
             c.ContentType.Alias == GenericContent.ModelTypeAlias ||
             c.ContentType.Alias == StoryContent.ModelTypeAlias ||
             c.ContentType.Alias == PodcastItem.ModelTypeAlias))
            {
                if (contentItem.GetValue("pagePostTags") != null)
                {
                    var parentId = contentItem.ParentId;
                    IEnumerable<string> tags = contentItem.GetValue<string>("pagePostTags").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    foreach(var tag in tags)
                    {
                        CreateTopicNode(tag, parentId);  
                    }

                }

            }
        }

As you'll see in the code above, when someone clicks Save and Publish, the event is hit and in this scenario I check to see what Content Type is being published. I only want this Topic page to be created if one of the specific Content Types is published.

Once the check has been done and the publish is being sent from the correct node, I then check to see if the Tag picker has a value. The Tag picker alias in my example is pagePostTags.

Before you can save the new Node, you need to know where you want to save it. In this example, I'm saving the node at the same level as the page I'm creating.

I will explain this a bit. If I have a parent node called Blogs, I then create a new Blog article under this node. When I click publish on the Blog article, I also create a Topic page under the Blogs parent. I hope that makes sense.

 IEnumerable<string> tags = contentItem.GetValue<string>("pagePostTags").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);

The code above was kindly supplied by Janae who is an awesome dev who I was chatting with on the Umbraco Community Slack channel. Without her help I would have been stuck with the Tags. Thanks Janae!

What it does is, it reads the property value and splits each tag in to individual tags.

This needs to be done so that if 4 tags are set on the page, I can create 4 different topics pages.

Now comes the fun bit of creating the Topic page.

 private void CreateTopicNode(string tag, int parentId)
        {
            IContentService contentService = ApplicationContext.Current.Services.ContentService;
           
            var nodeExists = new UmbracoHelper(UmbracoContext.Current)
                .TypedContentAtRoot()
                .DescendantsOrSelf(TopicHomepage.ModelTypeAlias)
                .Any(n => n.Name == tag);
            
            if(nodeExists == false)
            {
                var content = contentService.CreateContent(tag, parentId, TopicHomepage.ModelTypeAlias);
                content.SetValue("blogPostTitle", tag);
                contentService.SaveAndPublishWithStatus(content);

            }
        }

What the code above does is it checks to see if the Topic page already exits. If it does then we don't create a new one, if it doesn't then we create a new TopicHomepage node type and pass the tag name as the Node name.

I also set the property value blogPostTitle as the Tag name. In this example, the blogPostTitle is just a textstring property.

Once this has been done, I use the content service and Save and Publish this new node under the parent.

As a side note, this doesn't create the TopicHomepage document type, you need to create that manually but once you have it created, there is nothing else needed.

Happy coding!

Published on: 24 February 2021