Ticket (Solved)

How to override a widget's view contained in a Layout Projection?

Hey Guys, I have been trying to access my custom 'Slider Widget' in a page's layout [contained in a Layout.projection] without success? I wish to change my widget's view for the summary [to simplify it] as opposed to my detailed view.

So, I have a projection [layout projection] made up of pages and simply wish to edit/restructure the summary view of that projection via an alternate view found at: Content-Page-SitesTaxonomy-websitetaxonomy.Summary

Though, when I debug this view I assume that the layout segment of a projected page where the widget I wish to access should be contained in: Model.ContentItem.Parts.LayoutPart --> (My slider widget), though I can't seem to reference it as it's apparently hidden in a recursive cycle of layoutParts/Data?

I have researched as much Orchard info as I can (which is very confusing due to being outdated when referencing forum replies etc.) and think I can achieve what I want with Fields, Zones, and Placement.info; but of course, I lose all the benefits of layouts and what I have already created [so that certainly isn't the answer].

Can anyone shed some light on how to go about what i'm after with layouts? Or am I completely on the wrong track? Many thanks in advance as I have slammed into a brick wall :/

Re: How to override a widget's view contained in a Layout Projection?

So it looks like Layouts handles displaying content very differently to what I've been reading about Orchard of old.

In {Orchard.Layouts.Models.LayoutPart} there is LayoutData which contains the element I wish to override within a string:

....."elements\":[{\"typeName\":\"FeaturedItemSliderWidget\",\"data\":\"WidgetId=6285\",\"exportableData\":\"\",\"index\":0,\".....

Is it possible to edit this string and insert a new View template for the FeaturedItemSliderWidget considering it's yet to be built? As I type this, it just doesn’t seem right - as in - very complicated for something that appeared to be possible in a much easier fashion with earlier Orchard [but I could be misreading the literature as well]? Am I just not understanding something bery basic? Thanks for any suggestions you can offer my way as I'm terribly confused :\

Monday, July 18, 2016 2:22:08 AM bypug
  • pug
  • Lv. 04 Rookie
  • Total EXP: 144

Re: How to override a widget's view contained in a Layout Projection?

Hey guys, as this question isn't attracting many responses -ha, I thought I'd clear up what i'm after with hopefully this simple graphic ;)

https://i.imagestash.io/y7MzddzwJn.jpg

The Green circle is what i'm trying to achieve [the red is what I have, currently], which I believe hinges on being able to access LayoutData before it is built, amending it, then passing it on? Or, if this is impossible to achieve - how do I go about it another way without Layouts? Thanks in advance, 'the Extremely desperate'.

Wednesday, July 20, 2016 6:20:09 AM bypug
  • pug
  • Lv. 04 Rookie
  • Total EXP: 144

Re: How to override a widget's view contained in a Layout Projection?

Hi pug,

I see what you're trying to do, and I have good news: it's all quite possible without having to do any qeird manipulation of the layout data's JSON string.

In fact, you should already be seeing the slider widget being rendered out of the box. The fact that you don't seems odd.

Point in case, I tried the same scenario, only I used the HTML widget as an example. This is what I did:

  1. Create a Query
  2. Create a content item (that will be returned by the query) and add an HTML widget to it.
  3. Add a Projection Element to a page that is not returned by the query.
  4. You will see the content item being rendered including the widget: see below image:

Image Text

(Only one content item is being returned by the query, but you can see that it renders the widget).

I suspect that you did some shape template overrides and maybe did something that broke. Perhaps you could share the relevant views, or maybe even zip up some of your files and provide instructions to get to the point where you are at currently?

Thursday, July 21, 2016 6:43:58 PM bysfmskywalker

Re: How to override a widget's view contained in a Layout Projection?

PS. I love the pictures you created - makes the situation so much more clearer!

Thursday, July 21, 2016 6:48:14 PM bysfmskywalker

Re: How to override a widget's view contained in a Layout Projection?

Also, to answer your question as stated in the title of this ticket, it turns out you currently can't create an override for the widget being rendered as part of a layout element. Well, you could, but you would change the widget everywhere else too.

To fix that, you need the ability to provide a custom display type for the widget being rendered. This could be done as a simple property we would add to the widget elements, which would be quite easy to do. If this is something that you need, then please feel free to create an issue for it on GitHub.

Thursday, July 21, 2016 6:52:05 PM bysfmskywalker

Re: How to override a widget's view contained in a Layout Projection?

Ha ha, thanks @sfmskywalker - I'm definitely more a visual person so graphics always helps ;).

I believe what you have denoted in your steps does work, though wouldn’t help my situation as I still need to amend the results to adjust the positioning of the Slider...Instead of being items placed one atop of the other, I need the Slider to be in an Aside Div, with the summary blurb beside it [unlike its detailed view which is fine one after the other].

Hence, funnily enough, I had already started down the path you suggested at the end of your responses to provide my own DisplayType…I just added [copied your detail result]:

protected override DriverResult Display(LayoutPart part, string displayType, dynamic shapeHelper)
...
ContentShape("Parts_Layout_ProjectionSummary", () => {
                if (DetectRecursion(part, "Parts_Layout"))
                    return shapeHelper.Parts_Layout_Recursive();

                var elements = _layoutManager.LoadElements(part);
                ...

And updated the placement file to see if it would pass this displaytype to my widget. Unfortunately, the display type only holds true for the rendering of the initial layout, but then doesn’t pass it down the line to the children layouts in the projection; hence, when it gets to my widgets display driver, it is still 'Detail'. My intention was to create some zones in a wrapper, and upon the displaytype being 'ProjectionSummary' when passed to the slider driver, have the slider widget use a different shape and then render it in this 'aside' zone.

I can see this is indeed possible with more experience, and I believe, would be an immensiely powerful feature [like you suggested, a custom property?] so I will definitely add a Github Issue [forgive my inexperience, but I assume I do so at https://github.com/OrchardCMS/Orchard/issues section as there is no Layouts section?] And also, in the meantime - would you mind throwing some pointers my way at which code blocks I should look into amending re: Layouts/Widgets modules to achieve what I'm after, as I'm extremely desperate to get this to work. I would be more than happy to upload the results to github, but my coding isn't strong and I dare say it's something you could achieve in a matter of minutes, anyways - ha, but maybe I might discover some other pitfalls (...and after some extensive code vetting) you could apply the code. So sorry for the long winded and recursive questioning, but I truly do appreciate everything you have offered so far, and frankly, I'm ecstatic just to get a response from the layout's master and that there is a possibility it could work :) Pug

Friday, July 22, 2016 1:15:26 AM bypug
  • pug
  • Lv. 04 Rookie
  • Total EXP: 144

Re: How to override a widget's view contained in a Layout Projection?

Hi @Sipke, I opened a GH issue at: https://github.com/OrchardCMS/Orchard/issues/7048 - hope that is alright?

Just to confirm: Am I to understand that all elements are 'really' built with the "detail" display type, for if you choose summary - it really only takes a snippet of the html built as detail, anyway:

var excerpt = new HtmlString(Html.Excerpt(layoutHtml, 200).ToString().Replace(Environment.NewLine, "</p>" + Environment.NewLine + "<p>"));

So when I changed my display type in Queries --> Layout -->Raw [display type= "summary"], all the elements within that build receive display type 'detail' [or null, which becomes detail by default], then the above code happens -- to me this has been why I've struggled so much with this topic and appears to be so counter intuitive? I really thought the elements would receive the displayType you denoted. If this is the case, my GH issue isnt so much a feature request, but more so a bug? What do you think? Thanks for your efforts, Pug

Saturday, July 23, 2016 2:52:15 AM bypug
  • pug
  • Lv. 04 Rookie
  • Total EXP: 144

Re: How to override a widget's view contained in a Layout Projection?

Here just for info because i got something working but i needed to update some source codes. Would need more investigation and maybe some drawbacks in other scenarios, but here the idea.

  1. As said in your other ticket, to prevent your driver from being called when editing and without having to detect if you are in the admin in your razor view, in ProjectionElementDriver.cs use this:

        // after this line
        context.ElementShape.ContentItems = contentItems;
    
        // Nothing more to do if we are in "Design" mode.
        if (context.DisplayType == "Design")
        {
            return;
        }
    
  2. In LayoutPartDriver.cs to retrieve all elements when displayType = Summary, use this:

    ...
    ContentShape("Parts_Layout_Summary", () => {
        if (DetectRecursion(part, "Parts_Layout_Summary"))
            return shapeHelper.Parts_Layout_Summary_Recursive();
    
        var elements = _layoutManager.LoadElements(part);
        var layoutRoot = _elementDisplay.DisplayElements(elements, part, displayType: displayType);
        return shapeHelper.Parts_Layout_Summary(LayoutRoot: layoutRoot);
    }));
    
  3. To render these elements, copy / paste Parts.Layout.cshtml in Parts.Layout.Summary.cshtml:

    <div class="orchard-layouts-root">
        @Display(Model.LayoutRoot)
    </div>
    
  4. Finally, in Orchard.Widget.WidgetElementHarvester.cs, in the Displaying() method, use this:

    //var widgetShape = widget != null ? _contentManager.Value.BuildDisplay(widget) : default(dynamic);
    
    var widgetShape = widget != null ?
        _contentManager.Value.BuildDisplay(widget, context.DisplayType) : default(dynamic);
    

Then, when debugging, in the BodyPartDriver (for testing i use an html widget element), i can see that this is the Parts_Common_Body_Summary delegate which is executed. Note that in your custom driver you also need to implement the summary shape (see in BodyPartDriver as an example).

Best

Sunday, July 24, 2016 4:06:57 AM byjtkech
  • jtkech
  • Lv. 13 Rookie
  • Total EXP: 1028

Re: How to override a widget's view contained in a Layout Projection?

OMG - I just got all excited because I discovered the Missing ""context.DisplayType"" in the Harvester:

var widgetShape = widget != null ? _contentManager.Value.BuildDisplay(widget, context.DisplayType) : default(dynamic);

Which should basially solve all my problems, itself - I mean, what are the odds you would post that as I was :)

Sunday, July 24, 2016 4:18:01 AM bypug
  • pug
  • Lv. 04 Rookie
  • Total EXP: 144

Re: How to override a widget's view contained in a Layout Projection?

...Clearly you were ahead, I'm not saying that, I'm just chuffed I managed to sort it myself - that is a definite BUG in my opinion, for Widgets could never work properly without it and against anticipated convention. Anyhow, thanks heaps for you interest jtkech - I will have a look at your code and see how I go, but I know I can get this to work now - you LEGEND!

Sunday, July 24, 2016 4:20:46 AM bypug
  • pug
  • Lv. 04 Rookie
  • Total EXP: 144

Re: How to override a widget's view contained in a Layout Projection?

Major let down, after all that - I still can't achieve what I want - and I believe it all hinges on whether or not I can create Custom Zones in my shapes/views [please see: http://orchardpros.net/tickets/10839 ]? For if I can't, my ambition would be an absolute nightmare to implement. Thanks for any thoughts [I'm gutted - one step forward, two steps back] - cheers guys.

Monday, July 25, 2016 7:40:28 AM bypug
  • pug
  • Lv. 04 Rookie
  • Total EXP: 144

Post a reply

You need to be signed in to post a reply.

Sign In