Two custom widgets in one module?

Topics: Core, Customizing Orchard, General, Writing modules
Jul 31, 2014 at 2:03 PM
Edited Jul 31, 2014 at 2:08 PM
Hi, we are developing a custom module, where we load data from external DB and show them on pages by our custom routes. That's no problem. We created 1 widget shown in AsideSecond zone successfully - it shows our external data on the right column... But when we created second widget the same way (model, driver, handler, migrations etc.), it doesn't show on any zone - in html source there is empty "article" tag with genrated classes, but nothing more. When i debug these widgets and stop in their Driver definitions, both have data loaded correctly, but when i continue, it will render only first. After 3 days trying a lot of recommendations in forums, blogs etc. i can't solve it. But i found, when i change in Display method part "Parts_VavVyberOsoby" to part of first widget "Parts_VavSpravy", debug will stop in this cshtml file (i have stop mark in both cshtml files on razor's @if...) and orchard is trying load this view. It seems like there is problem with shapeHelper. I checked names of files, string parameters and all is OK.

First widget - driver display (works):
        protected override DriverResult Display(
            SpravyWidgetPart part, string displayType, dynamic shapeHelper)
        {
            return ContentShape("Parts_VavSpravy",
                () => shapeHelper.Parts_VavSpravy(ContentPart: part));
        }
First widget - part name: VavSpravy.cshtml (located in Views/Parts)

Second widget - driver display (doesn't work):
        protected override DriverResult Display(
            VyberOsobyWidgetPart part, string displayType, dynamic shapeHelper)
        {
            return ContentShape("Parts_VavVyberOsoby",
                () => shapeHelper.Parts_VavVyberOsoby(ContentPart: part));
        }
Second widget - part name: VavVyberOsoby.cshtml (located in Views/Parts too)

Working (but not acceptable) version of second widget Display return:
        protected override DriverResult Display(
            VyberOsobyWidgetPart part, string displayType, dynamic shapeHelper)
        {
            return ContentShape("Parts_VavSpravy",
                () => shapeHelper.Parts_VavSpravy(ContentPart: part));
        }
It really seems, like in one module should by only one Part (or Widget), but i didn't find any answer... Or is it Orchard's bug? Has anybody tried this?
Jul 31, 2014 at 2:06 PM
Check if you have an entry for the second widget shape (Parts_VavVyberOsoby) in the Placement.info file.


Jul 31, 2014 at 2:12 PM
Edited Jul 31, 2014 at 2:13 PM
Thanks, but yes:
<Placement>
    <Place Parts_VavSpravy="Content:3"/>
    <!--<Place Parts_VavSpravy_Edit="Content:3"/>-->
    <Place Parts_VavVyberOsoby="BeforeMain:5"/>
    <!--<Place Parts_VavVyberOsoby_Edit="BeforeMain:5"/>-->
</Placement>
Edit is commented, we don't have edit options for these widgets.
Jul 31, 2014 at 2:18 PM
Wow, i changed BeforeMain to Content and it starts working. Thanks for help, kassobasi. But i don't understand difference between Content and BeforeMain, both are zones...
Jul 31, 2014 at 2:18 PM
BeforeMain is not valid that way in the placement info. Since this is a widget, you need to use Content or some other *local zone* name, and place the widget to the *theme zone* BeforeMain using the admin panel widgets settings.

Alternatively you can put a forward slash before BeforeMain in the placement file to make it Parts_VavVyberOsoby="/BeforeMain:5" and the part will be rendered in there, but this time you lose the widget placement.


Jul 31, 2014 at 2:26 PM
Thank you for the explanation. I missed list of allowed values in documentation, but i'm a novice in the using and developing in Orchard.
Jul 31, 2014 at 2:44 PM
It's missing in the documentation I guess. The catch is, placement, originally, is about placing shapes of content parts of a content item relative to each other. Almost everything is a content item in orchard, and there is a Content.cshtml somewhere in the orchard core that renders the html for it. By default it renders an article tag with a header and footer and some content. If you check the source code of this file you can see there are four calls to Display method: Display(Model.Header), Display(Model.Meta), Display(Model.Content) and Display(Model.Footer). So Header, Meta, Content and Footer are the names of the local zones and they are to be used in the placement.info file. You can override Content.cshtml in your theme to render differently, e.g. a wrapping div instead of an article, or put Display calls in different places.

When dealing with an CMS "content" word is used to name many things, hence the confusion Content being a theme zone name (of the theme machine and virtually any other theme) and a local zone name.


Aug 1, 2014 at 8:42 AM
Thanks again, that's comprehensive answer.