How do I disallow blocks from being put in content areas that doesn't not have my selected tag?

Vote:
 

I am making a block that must only be put in few selected content areas. How do I go about this?

#179828
Jun 22, 2017 16:29
Vote:
 

Hi Benjamin,

You can decorate content areas with the AllowedTypes attribute. 

#179829
Jun 22, 2017 17:00
Vote:
 

So if I want to say that a content areas can contain all but that one block, how would I do that?

#179830
Jun 22, 2017 17:02
Vote:
 

Create a base class/interface which all block types should implement? It's also possible to create a page validator, but it doesn't provide nice editing experience. 

#179832
Jun 22, 2017 17:16
Vote:
 

The AllowedTypes attribute has RestrictedTypes property: http://world.episerver.com/documentation/Items/Developers-Guide/Episerver-CMS/9/Content/Properties/Property-types/Restricting-content-types-in-properties/

#179833
Jun 22, 2017 17:20
Vote:
 

There isn't a way I can declare on my block that it is only allowed in tagged content areas? Would be easier specifying this logic on the block rather than all the content areas. 

#179838
Jun 22, 2017 18:49
Vote:
 

How about creating a specific interface that you add to your Block?

For example:

public interface ITaggedContent : IContentData
{
}

[UIDescriptorRegistration]
public class TaggedContentUiDescriptor : UIDescriptor<ITaggedContent> { }

Implement this interface on your Content

public class MyBlock : BlockData, ITaggedContent
{
}

public class MyPage : PageData, ITaggedContent
{
}

And on your ContentArea add the AllowedTypes as Dejan mentions

[AllowedTypes(AllowedTypes = new[] { typeof(ITaggedContent) })]
public virtual ContentArea MyContentArea { get; set; }

You will need to have the UiDescriptor, otherwise AllowedTypes will not be able to understand that your pages and blocks implement this interface.

#179956
Edited, Jun 27, 2017 9:35
Vote:
 

I don't think that is what I need. I have a block SpecificBlock that I want to make sure is only placed on pages with page type SpecificPage. How do I go about this?

#180014
Jun 28, 2017 13:14
Vote:
 

Since there are no "exclude" for this in Episerver but only "include" there are no easy way to do this.

One way could maybe be to use the IValidate interface for all content types that would go through all ContentAreas on the content and make sure that the block is not added.

http://world.episerver.com/documentation/Class-library/?documentId=cms/10/2D086E18

So roughly the code should do

if(instance is SpecificPage)
{
    return Enumerable.Empty<ValidationError>();
}

and then loop all properties and validate each property value that is a ContentArea and send an error if something is wrong

var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();
var errors = new List<ValidationError>();
foreach (PropertyData property in CurrentPage.Property)
{
    var contentArea = property.Value as ContentArea;
    if (contentArea == null)
    {
        continue;
    }

    var contentLinks = contentArea.Items.Select(i => i.ContentLink);
    var contentAreaContainsSpecificBlock = contentLoader.GetItems(contentLinks, LanguageSelector.AutoDetect(true)).Any(content => content is SpecificBlock);
    if (contentAreaContainsSpecificBlock)
    {
        errors.Add(new ValidationError
        {
            ErrorMessage = $"{property.TranslateDisplayName()} contains SpecificBlock",
            Severity = ValidationErrorSeverity.Error
        });
    }
}

return errors;

It's just an idea but maybe something you can build on

#180015
Edited, Jun 28, 2017 13:35