NOTE: This is broken in Umbraco 11
Luckily, Duane Gibbs provided a workaround, that looks even better! #h5yr
Element Types in Umbraco is cool, and can be used as a user friendly way of building custom component based content for your pages. These can be built with the default Block List editor, Nested Content, Doc Type Grid Editor or other Element Type based editors.
But they come with a few limitations. One of them being, that they prevent a bunch of built in property editors like Tags, from being used in an Element Type.
In this article I will show you how you can bypass this, and still get to use tags in your Element Type based components.
But why can't I just use the default tag editor?
Tags are disabled in element types, because the tag editor does much more than just adding some text labels in a specific property. When you save a node with tags, an index of tags and their related nodes are created, for you to search in. So as an example, you can find all nodes tagged with codegarden
, by using a TagQuery with the Umbraco Helper. This requires the nodes to be actual nodes - which element type based nodes is not. They are just json blobs stored in your nodes, and the TagQuery can't find tags inside that.
Since the prevention is based on the property editor alias, all you need is a tag-editor with a non-standard alias.
The solution - make a duplicate with another alias
Typically - at least from my point of view - you want to use tags in Element Types, to filter content inside a specific component. Like a list of articles from a specific tag. Or you just like the UI of the editor, and want to use that. So in my case, I can live without the indexing of tags, and I just need the editor.
Luckily you can create your own tag editor, without much work, by simply inheriting stuff from the default one.
So open up your favorite code editor, and add a package.manifest
in your desired App_Plugins
folder. I have created this one in App_Plugins\Tags.DataOnly\package.manifest
. Don't know what a package.manifest is? The documentation has got you covered.
{
"propertyEditors": [
{
"alias": "Umbraco.Tags.DataOnly",
"name": "Tags (Data Only)",
"icon": "icon-tags",
"group": "tags",
"editor": {
"view": "tags"
},
// ...
All the values is lifted from the default tag definition (lines 18-22), with just one modification. I added ".DataOnly" to the alias, and "(Data Only)" to the name, to separate it from the default tags editor.
I also need some configuration fields, for specifying which group of tabs to select from, in addition to a storage type for the property.
// ...
"prevalues": {
"fields": [
{
"label": "Tag group",
"description": "Define a tag group",
"key": "group",
"view": "requiredfield"
},
{
"label": "Storage Type",
"description": "Select whether to store the tags in cache as JSON (default) or as CSV. The only benefits of storage as JSON is that you are able to have commas in a tag value",
"key": "storageType",
"view": "views/propertyeditors/tags/tags.prevalues.html"
}
]
},
// ...
These are lifted from the TagConfiguration class in the source code of Umbraco. Note how I just copy and paste everything, including the views.
At last, I need some default configuration. I could leave this out, but I like that the experience is as close to the default, so this is added like this:
...
"defaultConfig": {
"group": "default",
"storageType": "Json"
}
...
With the default config in place, I could also enable this editor to be used in macros, by simply adding the isParameterEditor
property to my manifest.
With all this in place, I can now go to Umbraco, and use my new Tags (Data Only) editor as my tag editor in Element Types.
Make ModelsBuilder behave - wrap the value converter
But there is one thing missing. The default editor returns a list of strings, when used with ModelsBuilder, and I would like this one to do the same.
Turns out, this is pretty simple too.
I can add my own ValueConverter, that simply inherits from the default TagsValueConverter.
using Umbraco.Core;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors.ValueConverters;
using Umbraco.Core.Services;
namespace TagsDataOnlyProject
{
public class TagsDataOnlyValueConverter : TagsValueConverter
{
public TagsDataOnlyValueConverter(IDataTypeService dataTypeService) : base(dataTypeService)
{
}
public override bool IsConverter(IPublishedPropertyType propertyType)
=> propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.Tags + ".DataOnly");
}
}
Umbraco automatically picks this up when booting, and I now have a list of strings as the output type for all properties using my Tags (Data Only) editor.
Photo by rizki ramadhan on Unsplash
Top comments (3)
I couldn't get this to work in v11, it seems something has changed with how the property editor configuration is parsed.
The base
TagsValueConverter
expects the editor configuration to be an instance ofTagConfiguration
however you get aDictionary<string, object>
using a package.manifest with 'prevalues' approach. This results in an invalid cast exception in the base class when trying to figure out what storage type has been used.The workaround is to register the 'Data only' tags editor via C# class by inheriting from
TagsPropertyEditor
.e.g:
[DataEditor("Umbraco.Tags.DataOnly", "Tags", "tags", Icon = "icon-tags", ValueEditorIsReusable = true)]
public class TagsDataOnlyEditor : TagsPropertyEditor { //... }
The base
TagsPropertyEditor
ensures the configuration object is created in the correct format.Not when you use it this way. The typeahead works by looking at actual tags being created. Since tags can only be created on real nodes (and not elements in a node), they wont be created.
I love this. Thanks for this. My question is, as I add tags to one input, will other inputs using the same new tag editor be able to typeahead the previous tags because they belong to the same group?