need some guidance - fields, parts, modules - which way to go?

Topics: Customizing Orchard, Writing modules, Writing themes
Nov 28, 2011 at 12:22 AM
Edited Nov 28, 2011 at 12:22 AM

Everyone, Orchard n00b here looking for a bit of guidance. What I want to do seems relatively simple, and I'm not sure the "best" way to go about solving my problem.

I have a custom page layout (Content-Page.cshtml) that looks something like this:

@using Orchard.Utility.Extensions;
@{
    Layout.Title = "Tri Shop - " + Model.Title;
    Style.Include("Layout");
}

<!-- Content-Page.cshtml -->
<div id="content" class="bg-white left">
    <div class="story-panel-edge left no-left-border">
        @Display(Model.Content)
    </div>
    <div class="double-wide-edge-borderless single-tall right">
        <div class="small-block left border"></div>
        <div class="small-block-edge right no-right-border">
            @Display.Parts_Navigation_Menu()
        </div>
    </div>
    <div class="side-panel-edge right no-right-border">
        <!-- THIS IS WHERE I WANT MY IMAGE TO GO -->
    </div>
</div>

 What I want to do is add a custom field/part/module to the Page content type so that someone creating a page can select a special image that will be seen, for that page, in a panel on the right side of the page. I want the main Page content to be displayed in the main panel, given the class "story-panel" in the code above. How should I go about doing this?

I tried creating a custom field called ImageUrl where I would just put the image name, but the ImageUrl content is displayed via @Display(Model.Content). So now I'm going down the route of creating a custom module containing a custom record, custom part, and custom Migration but that seems like a lot of work for something that should be fairly trivial.

My first goal is just to make it work - I can upload images to the correct folder and just use a url text string to identify the image name associated with a specific page. However, the longer term goal is to have a custom part that allows someone creating a new page to upload the image that will be displayed. Given that goal, what is my best path?

My biggest failing is in figuring out how to render individual parts/content to my custom layout. Clearly, Model.Content isn't going to grab only the body content but instead will grab all page content. How do I just get the body content and how do I get other content, such as custom fields or parts that exist on the page?

Developer
Nov 28, 2011 at 10:17 AM

It looks that you could do the following:

  1. Install the module from the Gallery that adds an attachment part (I'm not sure which one is that, just search for "attachment"; there're multiple possibilities). Now you can add that part to the page content type, so when editing a page an image (or any other media, but let's stick to this) can directly be added.
  2. The attachment is nowhere displayed, despite attached to a page item. You could create a simple shape template that displays an image, fill it with the attachment path and dispatch it to the zone where you want your image to be rendered, just as Bertrand has described here. This "dispatching" can most easily done from a Handler (basically the most straightforward approach would be to write an event method [look at module's handlers how these work] attached to the attachment part, check if the type the attachment is attached to is a Page, if yes, create the shape and pass it the attachment url: either IOrchardServices.New.ShapeName(attachmentPart.UrlOrSomething) or IShapeFactory.ShapeName(attachmentPart.UrlOrSomething) where what I've written as interfaces are implementations of these types, injected through the constructor).

Of course if you want the whole thing to be bullet-proof, a nicer solution would be to roll out a brand new module specialized just for this task, but I think the above would be good too.

Hope this isn't too vague.