Virtual Happy Hour this month, Jun 28, we'll be getting a sneak preview at our soon to launch SaaS CMS!

Try our conversational search powered by Generative AI!

Create a new block on a page with min 1 sub-block

Vote:
 

Hi,

I have a block "accordion" that has to have a minimum of one accordion items.
If I now create a new accordion under blocks, I can add a new item with "Create a new Block" in its contentArea.
But if I create a new accordion directly on a page, I can only add a new item via the "Select Content" button.

As I have restricted the contentArea of the accordion to minimum of one item, I always have to first select an existing accordion item from the "Blocks", save the so created accordion, then remove the assigned accordion item and add a new one with "Create a new Block". This seems to be a bit weird and not really usefull for the editor.

Even if I build my own ValidationAttribute, this behavior exists. Am I missing something or is this the expected behavior?

Kind regards

#303106
Jun 07, 2023 13:25
Vote:
 

Hi,

I suspect that behaviour will come down to where the child block would be created. When you click to create a new block directly in a content area, it's created in the "For this Page/Block" folder associated with the content item with the content area. In your case, the validator is blocking the creation of the accordion block so it wouldn't have a "for this block" folder yet and hence can't have any items created from within its content area.

I suspect you could resolve the issue by disabling the validation until the block has been created. If you're creating your own validation attribute, you should be able to check whether the contentLink.ID is 0 for the content being validated and, if so, skip the item check.

#303110
Jun 07, 2023 16:50
Vote:
 

I've handled this requirement in two different ways now:

Option 1: Use custom Validations instead

Remove the [Required] or [MinElements] attributes from the ContentArea and create a custom validator for the parent block using IValidate<TBlock>.  This validator can then return a ValidationError with a "Warning" or "Information" severity instead stating that at least one child block is needed for the parent block to render.  I've then added a condition within the ViewComponent for the block which returns an empty content result if there is not at least one child block.

public class ParentBlockValidator : IValidate<ParentBlock>
{
    public IEnumerable<ValidationError> Validate(ParentBlock instance)
    {
        if (instance.Children.IsNullOrEmpty())
        {
            yield return new ValidationError
            {
                ErrorMessage = "At least one child block is required for this block to be valid",
                Severity = ValidationErrorSeverity.Warning,
                PropertyName = nameof(ParentBlock .Children)
            };
        }
    }
}

public sealed class ParentBlockViewComponent : BlockComponent<ParentBlock>
{
    protected override IViewComponentResult InvokeComponent(ParentBlock currentContent)
    {
        if (currentContent.Children.IsNullOrEmpty())
        {
            return Content(string.Empty);
        }
        return View(currentContent);
    }
}

Option 2: Use the new way of doing things

In the 12.18 + world you could use the IList<TBlock> property instead which puts the child blocks into the same publish approval life cycle as the parent block.  Granted you lose the ability to use visitor groups on the Children property, but it makes management of Parent / Child content much nicer than using a ContentArea or a PropertyList implementation.

[ContentType(
    DisplayName = "Parent Block",
    GUID = "03FCAB3B-2711-4320-81D9-7D7CEF2978B7")]
public class ParentBlock : BlockData
{
    [MinElements(1)]
    public IList<ChildBlock>? Children { get; set; }
}

[ContentType(
    DisplayName = "Child Block",
    GUID = "AA287F83-9486-4B9F-8A8B-B477978656D7",
    AvailableInEditMode = false)]
public class ChildBlock : BlockData
{
    public virtual string? Title { get; set; }

    public virtual XhtmlString? Body { get; set; }
}
#303176
Jun 08, 2023 13:17
RJK Condor - Jun 09, 2023 5:49
Thank you very much, these solutions are great. I'll check if I would need visitor groups. Option 2 looks nicer to me.
Option 1 could fail for the rendering as we are running headless with NextJS ;-). But I'll give this problem to the FrontEndGuys.
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.