Question

I am trying to conditionally suppress a widget from its driver. I basically have logic that if met, should display the widget and if not, should suppress it. The widget loads properties from the current page content item, and based on some properties should display or hide. I've got all the logic working, the only part left is suppressing the actual output.

I've tried returning null from the driver, however this simply outputs an empty widget (with its wrapper). How do I completely remove the widget from view?

Finally, the zone that this widget is placed in should suppress if none of the conditional widgets display.

Is this type of flexibility possible in Orchard? Preferably from my custom module not my theme, I'm trying to separate functionality from styling.

EDIT:

Here is the context of my situation and what I am trying to accomplish. I'm sure there is a much cleaner way to do this within Orchard than how I have naively designed it the first go-around: My client's copywriters tag pages as they see fit (using the Tags module/part). I have created 2 custom content types, "Testimonials" and "Offers", both with tags themselves among other properties [these are managed by a different team of copywriters].

On most "inner pages" of the website (I'm using a layer to determine the appropriate pages), the page's sidebar gets a "Testimonial" widget and a "Offer" widget. These widgets both operate the same, although independently of each other:

They grab the tags of the current page, then pull a random [Testimonial|Offer] that has any matching tags as well. There are 4 cases that can happen given any inner page: a testimonial is displayed and the offer is hidden (testimonial tag matched, offer tag didn't), the testimonial is hidden and the offer is displayed, both the testimonial and offer displays, and finally neither displays. The first 3 use cases are working great, the 4th is what I'm having difficulty with, as the sidebar [zone] still displays even if both widgets do not (returning null from their respective drivers).

Was it helpful?

Solution

A bit of context about widgets: widgets are supposed to be pieces of contents that are visible on some or all pages of the site, and that provide information that is not directly related to the main content item on the page (if there is such a thing).

As a consequence, what you are describing should not be implemented as widgets (all that you had to do to make it work attests to that further), because they are really part of the content item. Instead, you should have implemented a part or a field. You can then simply place the shape for this part of field, using placement, by specifying a top-level zone: <place the_shape_name="/the_zone_where_you_want_it:1"/>

OTHER TIPS

Unfortunately I've had to use a bit of a hack so that I could move on with the project as I'm under an aggressive deadline, but if there is a better method and/or solution I'll test as I get the chance and mark as the answer.

To get it to work, I overwrote the Widget.Wrapper.cshtml file within my theme. There, I assigned a variable to the Display(Model.Child) call, and if the result is an empty string simply return. This removes any empty widget wrapping tags. (I personally feel Orchard should behave this way by default):

var child = Display(Model.Child);

// -- NOTE: shape tracing breaks this logic!
if (string.IsNullOrWhiteSpace(child.ToString())) {
    return;
}

Then simply replace the @Display(Model.Child) between the header and footer with @(child)

I then added the following method to my Layout.cshtml file.

Func<dynamic, IHtmlString> CollapsableZone = x =>
{
    var display = Display(x);
    string zoneName = x.ZoneName;
    if (string.Equals(display.ToString(), string.Format("<div class=\"zone zone-{0}\"></div>", zoneName.HtmlClassify()), StringComparison.CurrentCultureIgnoreCase))
    {
        return new HtmlString(string.Empty);
    }
    return display;
};

Simple function that assigns the display call to a variable, checks if it is an empty zone tag, and returns. I then create variables for each zone assigned to the value of the function above. I replace all the @if (Model.ZoneName != null) with @if (!string.IsNullOrWhiteSpace(zoneVariable)), and replace the calls to @Zone(Model.ZoneName) with @(zoneVariable).

This is working for the time being. It is quite a hack and brittle solution but I've had to move on to other things.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top