Try our conversational search powered by Generative AI!

Ben  McKernan
Dec 3, 2013
  14949
(3 votes)

Restricting the allowed types in a content area

A feature that was sorely missed in EPiServer 7 was the ability to restrict the type of content that could be dragged and dropped into a content area. Well, you will all be glad to know that in EPiServer 7.5 the content area has received a lot of loving and it is now possible to restrict the content types that can be dragged and dropped into it.

Something else that is also worth mentioning is the fact that media is also IContent now. So you can say goodbye to those silly ImageBlock and VideoBlock implementations that I know you all have, because this change means that it is possible to drag and drop image or video content directly into the content area.

These two changes open up a world of use cases for the content area. For example, image galleries or image carousels where the user can simply drag an image into the content area and it is added to the gallery or carousel. Another use case might be that you want to restrict which blocks can be added to a content area in the sidebar or footer or on the home page.

The Code

The edit interface is built up based on metadata for each property. This metadata includes the editor widget to use and also any default configuration that the widget should be initialized with. This metadata can be customized via an editor descriptor.

[EditorDescriptorRegistration(TargetType = typeof(ContentArea), UIHint = "Gallery")]
public class ImageGalleryEditorDescriptor : EditorDescriptor
{
    public ImageGalleryEditorDescriptor()
    {
        // Setup the types that are allowed to be dragged and dropped into the content
        // area; in this case only images are allowed to be added.
        AllowedTypes = new Type[] { typeof(IContentImage) };
 
        // Unfortunetly the ContentAreaEditorDescriptor is located in the CMS module
        // and thus can not be inherited from; these settings are copied from that
        // descriptor. These settings determine which editor and overlay should be
        // used by this property in edit mode.
        ClientEditingClass = "epi-cms.contentediting.editors.ContentAreaEditor";
        OverlayConfiguration.Add("customType", "epi-cms.widget.overlay.ContentArea");
    }
}

Here you can see that we've set allowed types to only include IContentImage types. So any class extending this interface can be added to the content area. This allowed types property automatically populates the relevant overlay and editor widget metadata, so that drag and drop will be restricted to images in both on-page and all properties editing modes.

The other two properties indicate which editor widget should be used and that a custom overlay should also be used. Unfortunately these need to be specified as we can't extend the ContentAreaEditorDescriptor and inherited them. This is a problem we are aware of and in the process of solving.

With that added to the project it is now just a matter of telling the relevant properties to use this editor descriptor rather than the default one. This is done via the UIHint that we added in the editor descriptor registration attribute. The attribute indicates that content area properties with a UIHint of Gallery should use this editor descriptor. So it is just a matter of adding a UIHint to the relevant properties.

[UIHint("Gallery")]
public virtual ContentArea Gallery { get; set; }

Caveats

The main thing to note is this only affects drag and drop in edit mode. So it is still possible to add other types of content via code.

The only other caveat that I've seen so far is that the editor and overlay for the content area both have some inbuilt help text that contains an action link for shortcutting to the block creation process. This process if followed through automatically adds the new block to the content area. Currently there is no way to configure this text not to display. It should be a fairly simple fix and there is a feature request for it so hopefully that should come soon.

Dec 03, 2013

Comments

Dec 9, 2013 09:45 AM

Cool. Sadly it doesn't seem to work with interfaces

The original ContentArea Descriptor has
this.AllowedTypes = (IEnumerable) new Type[1] { typeof (IContentData) };

But it doesn't work when I try with
this.AllowedTypes = new[] { typeof(IDropContent) };

Is it possible to add a restriction so that only the specific type may be added.
For example If I add StandardPage in the Alloy Templates, I am also available to add ProductPage that is a sub class of StandardPage.

Also the original ContentArea Descriptor has this override:
public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable attributes)
{
base.ModifyMetadata(metadata, attributes);
metadata.OverlayConfiguration["customType"] = (object) "epi-cms.widget.overlay.ContentArea";
metadata.CustomEditorSettings["converter"] = (object) "epi-cms.propertycontentarea";
}

Should they also be added in our custom descriptor?

Ben  McKernan
Ben McKernan Dec 12, 2013 10:43 AM

No unfortunately the only interfaces that will work are the base content interfaces. This is because we associate all content in the user interface with a UIDescriptor, and this association is calculated based on the left most branch of the inheritance tree. So if you have

public class MyBlock : BlockData, IDropContent

Then the UIDescriptor for BlockData will be what is chosen.

As for having restrictions, this is something that we talked about during development but didn't have time to implement, so it wasn't included. It is something that we could add as a feature later if there is demand for it.

Then to answer your last question, the metadata.OverlayConfiguration["customType"] is actually included in my example, I just added it in the constructor instead. As for the metadata.CustomEditorSettings["converter"] that is no longer used so can be safely ignored.

Dec 16, 2013 10:09 AM

You might want to check out this blog post: http://world.episerver.com/Blogs/Linus-Ekstrom/Dates/2013/12/Restriction-of-content-types-in-properties/

Feb 4, 2014 02:45 PM

In our current solution, we're also using validation, which makes sure the SlideShowArea will only contain SlideBlocks:

public class SlideShowValidator : IValidate
{
public IEnumerable Validate(SlideShowPage instance)
{
if (instance.SlideShowArea == null)
return Enumerable.Empty();

if (instance.SlideShowArea.Items.Any(item => !(item.GetContent() is SlideBlock)))
{
return new[]
{
new ValidationError
{
ErrorMessage = "Slides can be only of Slide Block type",
PropertyName =
ReflectionHelper.GetPropertyName(x => x.SlideShowArea),
Severity = ValidationErrorSeverity.Error,
ValidationType = ValidationErrorType.StorageValidation
}
};
}

return Enumerable.Empty();
}
}

Please login to comment.
Latest blogs
The A/A Test: What You Need to Know

Sure, we all know what an A/B test can do. But what is an A/A test? How is it different? With an A/B test, we know that we can take a webpage (our...

Lindsey Rogers | Apr 15, 2024

.Net Core Timezone ID's Windows vs Linux

Hey all, First post here and I would like to talk about Timezone ID's and How Windows and Linux systems use different IDs. We currently run a .NET...

sheider | Apr 15, 2024

What's new in Language Manager 5.3.0

In Language Manager (LM) version 5.2.0, we added an option in appsettings.json called TranslateOrCopyContentAreaChildrenBlockForTypes . It does...

Quoc Anh Nguyen | Apr 15, 2024

Optimizely Search & Navigation: Boosting in Unified Search

In the Optimizely Search & Navigation admin view, administrators can set a certain weight of different properties (title, content, summary, or...

Tung Tran | Apr 15, 2024