Skip to content

Bag (OrchardCore.Flows)

The BagPart is part of the Flows module, and is a content part that can contain multiple types of content items directly within it.

They are stored in the database as one single document, which makes them very powerful.

The BagPart shares a lot of similarities with the FlowPart in design, the difference is that with the BagPart you are able to specify exactly which content types can be contained within it.

This is done through the Settings for the BagPart.

BagParts may also be added to a Content Type Definition as a NamedPart. This allows one container item to have multiple BagParts.

An example of this can be found in TheAgencyTheme where four Named BagParts are used.

  • Services
  • Portfolio
  • About
  • Team

Templating in a decoupled manner

When templating in a decoupled manner the content items are accessed directly through the name of the BagPart.

{% for service in Model.ContentItem.Content.Services.ContentItems %}
    <h4 class="service-heading">{{ service.DisplayText }}</h4>
    <p class="text-muted">{{ service.HtmlBodyPart.Html | raw }}</p>
{% endfor %}
@foreach (var item in Model.ContentItem.Content.Services.ContentItems)
{
    <h4 class="service-heading">@item.DisplayText</h4>
    <p class="text-muted">@Html.Raw(item.Content.HtmlBodyPart.Html)</p>
}

In this example Services is a Named BagPart.

Templating with Display Management

When templating with Liquid the shape_build_display filter is used on the contained items to build the display shapes for the content items, then the shape_render filter is used to render these shapes.

When templating with Razor the IContentItemDisplayManager is used on the contained items to call BuildDisplayAsync to build the display shapes for the content items, then DisplayAsync is used to render these shapes.

<section class="flow">
    {% for item in Model.ContentItems %}
        {{ item | shape_build_display: "Detail" | shape_render }}
    {% endfor %}
</section>
@using OrchardCore.Flows.ViewModels

@model BagPartViewModel
@inject OrchardCore.ContentManagement.Display.IContentItemDisplayManager ContentItemDisplayManager

<section class="flow">
    @foreach (var item in Model.BagPart.ContentItems)
    {
        var itemContent = await ContentItemDisplayManager.BuildDisplayAsync(item, Model.BuildPartDisplayContext.Updater, Model.Settings.DisplayType ?? "Detail", Model.BuildPartDisplayContext.GroupId);

        @await DisplayAsync(itemContent)
    }
</section>

Template Alternates

The BagPart supports standard alternates and for a Named BagPart, you can include the name of the part, in the alternate.

MyBag-BagPart.liquid

MyBag-MyNamedBagPart.liquid

In the first example we have an alternate specifying the Content Type MyBag and the BagPart.

In the second example we have an alternate for the Content Type MyBag, and the Named BagPart MyNamedBagPart

The templates and alternate names for the Content Items contained in a BagPart are the same as standard Content Items.

Note

More alternates are available. You can examine these using the ConsoleLog Razor Helper or console_log liquid filter.

Placement Differentiator

The name of a BagPart is used as the differentiator in placement.json

  "BagPart": [
    {
      "differentiator": "MyNamedBagPart"
    }
  ]

Video