How to enumerate blocks of contentarea in view to render?

Vote:
 

How to enumerate blocks of contentarea in view to render? I have block1 and block2 in a contentarea and I want to render them separately unlike @Html.PropertyFor(x => x.CurrentPage.ContentArea).

Rather like below.
e.g.@Html.PropertyFor(block1 of contentarea)
@Html.PropertyFor(block2 of contentarea)

I tried to use Model.CurrentPage.ContentArea.Items.OfType<EPiServer.Core.BlockData>(). But how to use this in view?

#207692
Edited, Oct 01, 2019 9:15
Vote:
 

Hi Muller,

I think if you have created a view(Inside the Shared or View folder) of these blocks then you can directly render them using the below syntax

@Html.propertyFor(x=>x.CurrentPage.ContentAreaPropertyName)

It will automatically render all the blocks that are selected in that contentArea property.

And if don't have the view then you can enumerate through the item in that contentArea-

@foreach (var item in Model.CurrentPage.ContentAreaPropertyName)
{              
 <img src="@Url.ContentUrl(item.MobileImageBelow)" />  
 <p>@Html.Raw(item.Title) </p>          
}

But in that case, properties are not editable from On-Page-Editing view. So I suggest you go with the first approach and create a view for the block

#207694
Edited, Oct 01, 2019 7:32
Muller - Oct 01, 2019 9:15
I have updated the question.
Ravindra S. Rathore - Oct 01, 2019 9:42
I suggest you use two separate properties for this because it will be confusing to the content author in future and he/she needs to remember this.
Vote:
 

Hi Muller,

Do you want to perform this?

@foreach (var item in Model.MainContent.FilteredItems.OfType<BlockData>())
{
    if (item is CalloutBlock calloutBlock)
    {
        @Html.PropertyFor(x => calloutBlock.Title)
    }
    else if (item is ParagraphBlock paragraphBlock)
    {
        @Html.PropertyFor(x => paragraphBlock.CopyTop)
    }
}

Model.MainContent is the ContentArea property and you must be aware about FilteredItems (returns the publish items).

Here "is" will check if the type is a match then it will initialize that variable for example calloutBlock or paragraphBlock. You will have a strongly type object.

Thanks

#207695
Edited, Oct 01, 2019 8:32
Muller - Oct 01, 2019 9:16
I have updated the question.
Praful Jangid - Oct 01, 2019 9:17
This code is for view. I added this code in my view for HomePage.
- Oct 01, 2019 9:19
Does this really work? FilteredItems is of type IEnumerable of ContentAreaItem, and can't contain BlockData?
Muller - Oct 01, 2019 9:25
@praful jangid: I am using it in view.
FilteredItems yields no result. I tried Items instead it yields data but cannot render.
Praful Jangid - Oct 01, 2019 9:30
Items gives you all (published and unpublished items). FilteredItems gives you only Published items.
One more thing, which version of framework you are using? Because in older version "is" type check won't work.
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/is
Muller - Oct 01, 2019 9:33
All items are published. As I said FilteredItems yields no result; Items does but do not rendere. It's not about "is", I haven't used it.
Vote:
 

I think the last example will not work because FilteredItems contains ContentAreaItems. You will have to content load them. You may use the extension method GetContent from EPiServer.Core. ContentAreaItemExtensions.

@foreach (var item in Model.MainContent.FilteredItems.Select(x => x.GetContent()))
{
    if (item is CalloutBlock calloutBlock)
    {
        @Html.PropertyFor(x => calloutBlock.Title)
    }
    else if (item is ParagraphBlock paragraphBlock)
    {
        @Html.PropertyFor(x => paragraphBlock.CopyTop)
    }
}
#207707
Edited, Oct 01, 2019 9:47
Praful Jangid - Oct 01, 2019 9:51
Thanks Thomas, I missed that extension :)
Vote:
 

So, here FilteredItems will give you ContentAreaItem type in return. But to get the referenced item in backend we use ContentLoader by passing content link. Otherwise you can use the TemplateDescriptor and Tags to resolve the different view. For example, while rendering property use this

@Html.PropertyFor(x => x.MainContent, new { CssClass = "row", Tag = "MyTagName" })

For each CalloutBlockController use

[TemplateDescriptor(
AvailableWithoutTag = false,
Default = false,
ModelType = typeof(CalloutBlock),
Tags = new[] { "MyTagName"})]
public class CalloutBlockHomeController : BlockController<CalloutBlock>
{
}

For each ParagraphBlockController use

[TemplateDescriptor(
AvailableWithoutTag = false,
Default = false,
ModelType = typeof(ParagraphBlock),
Tags = new[] { "MyTagName"})]
public class ParagraphBlockHomeController : BlockController<ParagraphBlock>
{
}

Now, when you add even the CalloutBlock or ParagraphBlock into the ContentArea, it will resolve that view particular view and you will have your strongly typed object as model on that view.

#207708
Oct 01, 2019 9:50
* 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.