Episerver CMS: Ability to define supported block display options at a block level

Vote:
 

Currently in the CMS we define the different display options at a application leve via an InitializationModule. This then appies these sizes to all blocks across the site.

Within the Alloy Demo and also my company's standard base project we have features to allow when previewing blocks and adding them to page to show a message if an unsupported sizes is used. However is is really poor usability when you have no way for a user to know a block doesn't support a size until they have selected it.

Can we make it so we continue to use an InitializationModule to set up the options but we then have an Attribute which you would set on a block such as.

[DisplayOptions(DisplayOptionNames.Narrow, DisplayOptionNames.Full)]

Then the UI only displays the availible options per block in the CMS. It would also be have to have the DisplayOptions service updated to have methods to return supported sizes programatically.

#171754
Edited, Nov 17, 2016 12:46
Vote:
 

Hi Scott,

Thanks for the suggestion, will take this into consideration.

How much does the mark-up for different display options typically vary? Just different css classes? Or is the mark-up significantly different?

/Martin

#172232
Nov 28, 2016 14:00
Vote:
 

Also, would the display options in your example need to vary both on the block and the placeholder? i.e. a small placeholder for promo spots in a sidebar would presumably only work with the narrow option, while the same block in a large placeholder would support both narrow and full.

/Martin

#172233
Nov 28, 2016 14:05
Vote:
 

Thanks Martin,

The markup can sometimes in the views adapt such in the case of images where we server picture elements pushing through a dynamic image resizer but for the most part the markup itself is the same in the view. Where the markup differs is the wrapper classes that are added to the each blocks div element when going through our custom Content Area Renderer.

In our expereince the blocks don't have to different where they are put in as they area standardised in the UX and Design process for each supported size but certain blocks will never have certain sizes. For example we have full width hero images/videos that are only built to be used Full width and therefore should never have the option to display in Narrow or Wide. If we do ever need to vary anything by the container area its added to we would use Tags to render different Views or just adapt the blocks in our component SASS to where the block is added, we would only ever need the restriction of the sizes to be set at Block level, not contextually.

However to make it more Flexible maybe the option as passing the Layout options in to the PropertyFor would be nice if you needed to override them? However for our scenario is about the fact that every block is design as a component and can only support set sizes.

#172278
Nov 29, 2016 9:52
Vote:
 

Ok, thanks for expanding!

#172293
Nov 29, 2016 15:13
Vote:
 

It would be nice to have this

#174883
Feb 07, 2017 10:37
Vote:
 

On block level would be nice yes!

#174893
Feb 07, 2017 14:38
Vote:
 

Hi guys,

Was anyone able to use specific display options for a block?

#184545
Oct 31, 2017 6:31
Vote:
 

+1 for official support for this.

It is certainly possible to do right now, we have this functionality in our in-house site framework and have had since CMS 7.5.

If you know what display options you have for each model type, you can modify the display options menu by overriding the script "\modules\_protected\CMS\CMS.zip\[VERSION]\ClientResources\epi-cms\contentediting\command\SelectDisplayOption.js" and feed it with what display options are available by setting the variable this.popup.displayOptions in the _onModelChange function. We output the available display options for each modely type in a global js variable using the ClientResources framework in epi and reference that is the selectdisaplyoptions.js-script. Bit of a hack, but it works and is used in multiple live sites.

#187159
Jan 15, 2018 9:53
Vote:
 

Thanks @Erik, yeah I saw an article a while ago for version 7.5 which had stopped working due to being on 9 at the time. Dispite having experience in a lot of other JS frameworks Dojo is something I've never quite got round to playing with or extending episerver other than via C#. Is there's any change you'd post a blog or some examples with something that works with 10/11? It would be great to see something fresh that would help get this working

#187161
Jan 15, 2018 9:57
Vote:
 

I'm not sure about how episerver feels about me posting their source code, but ill try to only post our code and point to where it shoudl be located:

So first you would need to have some data to work with, we do this by outputting some global Js using the ClientResources framework, this is roughly how ours look:

	/// <summary>
	///     Provides the client resources required by Encore, avoids having to modify module.config
	/// </summary>
	[ClientResourceProvider]
	public class ClientResourceProvider : IClientResourceProvider
	{
		private static EncoreConfigurationSection Configuration => EncoreConfigurationSection.Instance;

	    /// <summary>
		///     This method is called when the client resources are collected
		/// </summary>
		/// <returns>
		///     A list of <see cref="T:EPiServer.Framework.Web.Resources.ClientResource" />s that this provider exposes.
		/// </returns>
		public IEnumerable<ClientResource> GetClientResources()
		{
			// this is the script you generate with display option restrictions
			yield return new ClientResource {
				Name = "epi-cms.widgets.base",
				Path = Paths.ToClientResource("", "encore/scripts/epi/displayoptionrestrictions.js"),
				ResourceType = ClientResourceType.Script
			};
			// this will override the built-in episerver script file with our hacked version
			// there is possibly a better way, more "correct" way to do this, but this works for us
			yield return new ClientResource {
				Name = "epi-cms.widgets.base",
				Path = Paths.ToClientResource("", "encore/scripts/epi/selectdisplayoption.js"),
				ResourceType = ClientResourceType.Script
			};
		}
	}

2. The data outputted by the disaplyoptionrestrictions.js looks like this, as you can see, there is both a list of content types with what tags they support, as well as a full list of all display options, the latter collection is for reference and retrieved by getting a service of the type EPiServer.Web.DisplayOptions and just json serializing all registered display options. How you want to populate the supported tags is up to you, but what you need to output is what tags a model supports (both bloks and pages works), the script will show all dispaly options if a model isnt present, so default is "show all".

//this is a list of what display options are supported by specific content types
//only content types that are restricted will be present here
var encoreSupportedTags = {
"acme.core.models.pages.articlepage": ["full","half"],
"__encore.alldisplayoptions": [{"id":"full","name":"Full","description":"","tag":"full","iconClass":"epi-icon__layout--full"},{"id":"twothirds","name":"Two thirds","description":"","tag":"twothirds","iconClass":"epi-icon__layout--two-thirds"},{"id":"half","name":"Halven","description":"","tag":"half","iconClass":"epi-icon__layout--half"},{"id":"onethird","name":"One third","description":"","tag":"onethird","iconClass":"epi-icon__layout--one-third"},{"id":"onequarter","name":"One quarter","description":"","tag":"onequarter","iconClass":"epi-icon__layout--one-quarter"}]
};

3. Last, we need to modify our own version of the selectdisplayoptions.js script originally found in "\modules\_protected\CMS\CMS.zip\[VERSION]\ClientResources\epi-cms\contentediting\command\SelectDisplayOption.js". If you copy the uncompressed version from epi, you need to insert the following code around line 65, after the line "isAvailable = isAvailable && (this.model instanceof ContentBlockViewModel);":

// begin display option hack
if (isAvailable && window.encoreSupportedTags != null) {
	if (window.encoreSupportedTags[this.model.typeIdentifier] != null) {
		var op = [];
		var i = options.length;
		while (i--) {
			if (window.encoreSupportedTags[this.model.typeIdentifier].indexOf(options[i].id) > -1) {
				op.push(options[i]);
			}
		}
		options = op;
		this.popup.displayOptions = op;
	} else if (window.encoreSupportedTags['__encore.alldisplayoptions'] != null) {
		var allOpts = [];
		for (var j = 0; j < window.encoreSupportedTags['__encore.alldisplayoptions'].length; j++) {
			allOpts.push(window.encoreSupportedTags['__encore.alldisplayoptions'][j]);
		}
		options = allOpts;
		this.popup.displayOptions = allOpts;
	}
}
// end display option hack

If everything works, your dispaly options menu should be limited for content types that has them, like below where the first block is an article page, and the second a regualr teaser without restrictions:

#187164
Jan 15, 2018 10:16
Vote:
 

Fantastic thanks @Erik you're a legend. I'll take a look at this later :-) this should certainly help to get this sorted until it's offical :-)

#187165
Jan 15, 2018 10:19
Vote:
 

Thanks again @Erik, I have took the base ideas of your code and hooked it in to a handler that generates all my restrictions through my existing custom attributes that I used on my project for restricting and controlling default sizes and allowed types and it's working like a charm. Legend!!

#187176
Jan 15, 2018 13:50
Vote:
 

Great, glad it worked! Now for some official support.. :-)

#187177
Jan 15, 2018 13:53
A
Vote:
 

Is this an out-of-the-box functionality yet?

#199072
Nov 14, 2018 17:26
Vote:
 

No not as yet but I've posted a full solution to this here https://world.episerver.com/blogs/scott-reed/dates/2018/4/controlling-episerver-display-options-via-a-custom-attribute/

#199170
Nov 19, 2018 9:51
Vote:
 

This should be out of box....
Lets upvote it!

#199171
Nov 19, 2018 11:13
Vote:
 

+ there should be a option to "define" default display option (not the case when block is created and display option is not set, but block gets very specific display option). either when block is added to the specific area or when block is created in any area. both cases should be covered. I did it for my Bootstrap aware area renderer, but should be OOTB.

#199194
Nov 20, 2018 5:25
Vote:
 

Yes, I also had a few comments on my blog post around some advance options so as far as I see it joining up what Valdis, myself and others have commented

  • Ability to define options globally in case specific block support isn't needed for a block
  • Ability to define via Attribute the block options
  • Ability to define some extra business rules for what options are displayed. E.g. visitor groups, profiles and ideally any other custom rules perhaps by creating a base class/interface for the class that resolves what should be displayed that we can override
  • Ability to define rules to combinations that are allow defending on a few things
    • Which parent type these blocks are in

I think it would also be good if these options could re-evaluate when any changes are made to layout instead of page loading. As if in our "layout rules service" we wanted to control the options related to sibligs or be aware of the context of where they are this would allow them to adapt as the page changes.

The top 2 highlighted are the most important to start I think, with the rest nice to haves.

#199197
Nov 20, 2018 9:00
Vote:
 

This is what I wish would be OOTB, we have these in our custom solutions as both attributes on blocks and through naming convention for view files:

  • Ability to restrict display options for individual blocks.
  • Ability to define the "Automatic" (or default) display option for a block, regardless of whats set in code for the content area.
  • Ability to define what view (.cshtml) should be used for a specific block and display option.
  • An easy way of defining available display options, such as in web.config. (maybe this is already possible?)
#199210
Nov 20, 2018 12:30
Vote:
 

if somebody is going to implement this, some of the inspiration could be found also here :) - https://github.com/valdisiljuconoks/EPiBootstrapArea

#199211
Nov 20, 2018 12:37
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.