matthewjamesr
matthewjamesr

Reputation: 63

Displaying Container Part Items From Content Picker Field

I have a content type called DayTile which I have setup with a content picker field that is limited to HotelSection type. This type is a container for the Hotels type.

I want to render all the hotels in the HotelSection when the DayTile has that section picked. Is this possible?

From what I have tried so far, it does not seem that the HotelSection's contained items are accessible as a content picker field.

Upvotes: 1

Views: 213

Answers (2)

Sipke Schoorstra
Sipke Schoorstra

Reputation: 3409

The selected content items are exposed by the ContentPickerFields ContentItems property (see Orchard.ContentPicker.Fields.ContentPickerField).

To access this from a DayTile content item, let's say from a Razor template named "Content-DayTile.cshtml", you would do it like so:

@{
    dynamic contentItem = Model.ContentItem; // How to access the content item depends on the context. In this case, we're in a Content shape template.

   // Assuming your picker field is named "HotelSections" and attached to your DayTile content type (which in reality means it's attached to an automatically created part called "DayTile").

   var picker = contentItem.DayTile.HotelSections;
   var hotelSectionContentItems = picker.ContentItems; // Typed as IEnumerable<ContentItem>.
}

<ul>
   @foreach(var hotelSectionContentItem in hotelSectionContentItems)
   {
      // You can now either access individual parts and fields of each hotel section content item and render it, or you can choose to build a shape for each item and display that. Here are examples:  

      <li>@hotelSectionContentItem.TitlePart.Title</li>

      // or: 
      // Build a content shape for the content item.
      var hotelSectionContentShape = BuildDisplay(hotelSectionContentItem, "Summary");

     // Render the shape.
     <li>@Display(hotelSectionContentShape)</li>
}

Upvotes: 2

Hazza
Hazza

Reputation: 6591

If I understand you correctly this should absolutely be possible.

You will want to override the Fields.ContentPicker view in your theme/module, and in the foreach loop instead of displaying a link to each HotelSection, you want to display that HotelSection content item, which in turn will display all the Hotels contained within the HotelSection, like so:

@using Orchard.ContentPicker.Fields
@using Orchard.Utility.Extensions;

@{
    var field = (ContentPickerField) Model.ContentField;
    string name = field.DisplayName;
    var contentItems = field.ContentItems;
}
<p class="content-picker-field [email protected]()">
    <span class="name">@name</span>
    @if(contentItems.Any()) {
        foreach(var contentItem in contentItems) {
            @Display(contentItem.ContentManager.BuildDisplay(contentItem, "Detail"))
        }
    }
    else {
        <span class="value">@T("No content items.")</span>
    }
</p>

If you are looking to access the Hotels directly from within the content picker field you will need to add a little bit more to the view, a little messy but like this:

@using Orchard.ContentPicker.Fields
@using Orchard.Utility.Extensions;

@{
    var field = (ContentPickerField) Model.ContentField;
    string name = field.DisplayName;
    var contentItems = field.ContentItems;
}
<p class="content-picker-field [email protected]()">
    <span class="name">@name</span>
    @if(contentItems.Any()) {
        foreach(var contentItem in contentItems) {
            var container = contentItem.As<ContainerPart>();
            if(container == null) {
                continue;
            }

            var hotels = contentItem.ContentManager
                .Query(VersionOptions.Published)
                .Join<CommonPartRecord>().Where(x => x.Container.Id == container.Id)
                .Join<ContainablePartRecord>().OrderByDescending(x => x.Position);

            foreach(var hotel in hotels) {
                // do something
            }
        }
    }
    else {
        <span class="value">@T("No content items.")</span>
    }
</p>

I'm missing some using statements at the top but the gist of it is there.

Upvotes: 2

Related Questions