Creating a content part with a list of custom content parts

Topics: Customizing Orchard, Writing modules
Sep 1, 2015 at 5:10 PM
I've been trying to write a simple accordian widget, where each section of accordian would be its own content part. I have the leafs content part created fine, but I want to create the accordian part which contains a list of the leafs. I havn't been able to find a good tutorial that went over something like this. I'm working on displaying the leafs now, and am running into issues. I'm trying to mimic the comments module. This is what I have. It seems like i am able to get up to the list of leafs in the driver, but i'm not sure what to do with the view. i see comments calls @Display(Model.List) but i have no idea what this is doing. Another thing is that my content is just a string. is there a way to have it use HTML for content instead of a string?

Edit View (Just using a textbox for one leaf id, need to figure out how to select leaves):
<fieldset>
    <legend>Accordian Fields</legend>

    <div class="editor-label">
        @Html.LabelFor(model => model.Title)
    </div>
    <div class="editor-field">
        @Html.TextBoxFor(model => model.Title)
        @Html.ValidationMessageFor(model => model.Title)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.AccordianLeaf)
    </div>
    <div class="editor-field">
        @*@Html.DropDownListFor(m => m.AccordianLeaf,
                                  new System.Web.Mvc.SelectList(service.GetComments(), "Value", "Text"))*@
        @Html.TextBoxFor(model => model.AccordianLeaf)
        @Html.ValidationMessageFor(model => model.AccordianLeaf)
    </div>
</fieldset>
Model:
namespace SuccessCenter.Models
{
    public class AccordianRecord : ContentPartRecord
    {
        public virtual string Title { get; set; }
        public virtual int AccordianLeaf { get; set; }
    }

    public class AccordianPart : ContentPart<AccordianRecord>
    {
        [Required]
        public string Title
        {
            get { return Retrieve(r => r.Title); }
            set { Store(r => r.Title, value); }
        }
        [Required]
        public int AccordianLeaf
        {
            get { return Retrieve(r => r.AccordianLeaf); }


       set { Store(r => r.AccordianLeaf, value); }
    }
}
}
Handler:
namespace SuccessCenter.Handlers
{
    public class AccordianHandler : ContentHandler
    {
        public AccordianHandler(IRepository<AccordianRecord> repository)
        {
            Filters.Add(StorageFilter.For(repository));
        }
    }
}
Driver:
namespace SuccessCenter.Drivers
{
    [UsedImplicitly]
    public class AccordianDriver : ContentPartDriver<AccordianPart>
    {
        private readonly IAccordian _accordian;

        public AccordianDriver(IAccordian accordian)
        {
            _accordian = accordian;
        }
        protected override DriverResult Display(AccordianPart part, string displayType, dynamic shapeHelper)
        {
            //return ContentShape("Parts_Accordian", () => shapeHelper.Parts_Accordian(Title: part.Title, AccordianLeaf: part.AccordianLeaf));
            return Combined(
               ContentShape("Parts_Accordian",
                   () =>
                   {
                       // create a hierarchy of shapes
                       var firstLevelShapes = new List<dynamic>();
                       var allShapes = new Dictionary<int, dynamic>();
                       var AccordianLeafs = _accordian.AccordianLeafs.ToList();

                       foreach (var item in AccordianLeafs)
                       {
                           var shape = shapeHelper.AccordianLeaf(ContentPart: item, ContentItem: item.ContentItem);
                           allShapes.Add(item.Id, shape);
                       }

                       var list = shapeHelper.List(Items: allShapes);

                       return shapeHelper.Parts_Accordian(
                           List: list
                           );
                   }));
        }

        //GET
        protected override DriverResult Editor(AccordianPart part, dynamic shapeHelper)
        {
            return ContentShape("Parts_Accordian_Edit", () => shapeHelper.EditorTemplate(TemplateName: "Parts/Accordian", Model: part, Prefix: Prefix));
        }

        //POST
        protected override DriverResult Editor(AccordianPart part, IUpdateModel updater, dynamic shapeHelper)
        {
            updater.TryUpdateModel(part, Prefix, null, null);
            return Editor(part, shapeHelper);
        }
    }
}
View:
@using SuccessCenter.Models;
}<div class="expand-view expanded">
    <header class="bg-brand-blue txt-white relative">
        <h3 class="txt-left">@Model.List.Title</h3>
        <span class="toggle v-align absolute">
            <span class="expanded">Colllapse <i class="icons icon-carat-up-wh"></i></span><span class="collapsed">Expand <i class="icons icon-carat-down-wh"></i></span>
        </span>
    </header>
<section class="default-padding">
    @Model.List.AccordianLeaf
</section>