November Happy Hour will be moved to Thursday December 5th.
November Happy Hour will be moved to Thursday December 5th.
One thing you could do is instead of hardcoding the text and values in the selection factory, you could put them as a configurable item in start page or a settings page so the value is configurable and dynamic.
Here is what I have used.
So if there is a change in the value you can update it on page and should reflect wherever you are using.
We normally create a separate Setting Page as Dileep suggested or you can use Translation strings to dynamically define these values (only use it if you are using dynamic translation provider)
Hi both,
Thanks for the responses. I've tried to set this up as a configurable property on the Start Page...
I’ve created a class of ButtonOption
public class ButtonOption
{
public string Text { get; set; }
public string Value { get; set; }
}
In my Start Page I’ve added the following (EditorDescriptor with button options and values defined beneath
[EditorDescriptor(EditorDescriptorType = typeof(CollectionEditorDescriptor<ButtonOption>))]
public virtual IList<ButtonOption> ButtonTypeOptions { get; set; }
public IList<ISelectItem> ButtonOption()
{
return new ISelectItem[]
{
new SelectItem {Text = "Blue", Value = "button-blue"},
new SelectItem {Text = "Black", Value = "button-black"},
new SelectItem {Text = "White", Value = "button-white"},
};
}
Selection Factory like so –
public IEnumerable<ISelectItem> GetSelections(ExtendedMetadata metadata)
{
var startPage = _contentLoader.Get<StartPage>(ContentReference.StartPage);
return startPage?.ButtonTypeOptions.Select(x => new SelectItem { Text = x.Text, Value = x.Value });
}
Block property -
public class MyBlock : SiteBlockData
{
[Display(Name = "Button type options", Order = 10)]
[SelectOne(SelectionFactoryType = typeof(ButtonOptionsSelectionFactory))]
[BackingType(typeof(PropertyString))]
public virtual string ButtonTypeOptions { get; set; }
When I run my solution though I get the following –
Type 'System.Collections.Generic.IList`1[[Domain.Models.Pages.ButtonOption,Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' could not be mapped to a PropertyDefinitionType
I had some trouble with the setup in the Start Page so I guess that's where i'm going wrong - appreciate any further help. Thanks.
Try defining property like
[Display(Name = "Button type options", Order = 10)]
[SelectOne(SelectionFactoryType = typeof(YourSelectionfactory))]
[BackingType(typeof(PropertyString))]
public virtual string ButtonTypeOptions { get; set; }
Thanks Naveed - still the same problem i'm afraid. Added the property as below -
public class MyBlock : SiteBlockData
{
[Display(Name = "Button type options", Order = 10)]
[SelectOne(SelectionFactoryType = typeof(ButtonOptionsSelectionFactory))]
[BackingType(typeof(PropertyString))]
public virtual string ButtonTypeOptions { get; set; }
Hi Jon
tested following solution in my local environment and it works
Start Page (or Settings page) property
[Display(Name = "Button Options List", GroupName = SystemTabNames.Content, Order = 220)]
[EditorDescriptor(EditorDescriptorType = typeof(CollectionEditorDescriptor<ButtonOption>))]
public virtual IList<ButtonOption> ButtonOptionList { get; set; }
Button Options property
public class ButtonOption
{
public string Text { get; set; }
public string Value { get; set; }
}
[PropertyDefinitionTypePlugIn]
public class ButtonOptionProperty : PropertyList<ButtonOption>
{
}
Selection Factory to get options from Start page (or settings page)
public class ButtonOptionsSelectionFactory : ISelectionFactory
{
private readonly Injected<IContentLoader> _contentLoader;
public virtual IEnumerable<ISelectItem> GetSelections(ExtendedMetadata metadata)
{
var startPage = _contentLoader.Service.Get<PageData>(ContentReference.StartPage) as HomePage;
return startPage?.ButtonOptionList.Select(x => new SelectItem { Text = x.Text, Value = x.Value });
}
}
Finally the property in your block
[Display(Name = "Button type options", Order = 10)]
[SelectOne(SelectionFactoryType = typeof(ButtonOptionsSelectionFactory))]
[BackingType(typeof(PropertyString))]
public virtual string ButtonTypeOptions { get; set; }
I hope that helps
Thanks again Naveed. This now works. I can see the new property on the start page and am am able to add some button type options e.g.
I can then access and set these properties in MyBlock.
However, one thing I noticed is that when I update the button type values in Start Page list e.g. change "button-black" to "button-bg-black" - the existing instances of the block continue to use "button-black".
This is my goal here to make sure if any of the values change then existing instances of the block will use the new values.
Feel so close now. Thank you for your help with this.
Jon - for your requirement you need a slightly different approach.
ButtonTypeOptions property stores a string copy of the dropdown value. When you update its values on start page -> ButtonOptionList, it would not update the copied value. All you need to do is store a key instead of value and get the value of key at run time. let me explain to you further
Your selection factory can have hardcoded items
public IList<ISelectItem> ButtonOption()
{
return new ISelectItem[]
{
new SelectItem {Text = "Blue", Value = "blue-key"},
new SelectItem {Text = "Black", Value = "black-key"},
new SelectItem {Text = "White", Value = "white-key"},
};
}
On the Start page, you will create a similar IList property that takes name & value but this time your name is key and value is actual CSS class.
such as
Name | Value |
blue-key | button-blue |
black-key | button-black |
Now when you render block, your ButtonTypeOptions property will give you value "blue-key" and you will check Start Page-> ButtonOptionList to get actual value of CSS ("button-blue")
Yes! Thank you very much Naveed. Working exactly as hoped for.
The last bit, as you mentioned, was to check the home page list of keys against the key value option selected in the block, which i've done in MyBlockController something like so -
private string SetButtonOption(string BlockBackgroundSelectedOption)
{
var ButtonBackgroundColors = _contentLoader.Service.Get<StartPage>(ContentReference.StartPage).ButtonBackgroundColors;
var BlockBackgroundColor = ButtonBackgroundColors.Where(x => x.Key == BlockBackgroundSelectedOption).FirstOrDefault().Value;
return BlockBackgroundColor;
}
Now any changes to the home page button option values is reflected any instances of MyBlock.
Thanks again.
That's great - You might want to put it in separate Helper class so that it can be used by other blocks/pages.
Hi,
I am using a selection factory to set a block type property as a CSS class.
The problem I have is that in the future the class name could change, for example if we change front end framework. In the example below the class name is given as 'button-blue' but could in the future be 'button-background-blue' but any existing instances of the block would continue to use the old classname.
Is there a better way I can write this to handle future class name changes?
Example code -
Class
Block type property
View -