<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><language>en</language><title>Blog posts by David Harlow</title> <link>https://world.optimizely.com/blogs/david-harlow/</link><description></description><ttl>60</ttl><generator>Optimizely World</generator><item> <title>Extending Commerce - Content Area Functionality</title>            <link>https://world.optimizely.com/blogs/david-harlow/dates/2018/3/extending-commerce---content-area-functionality/</link>            <description>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;By default, content areas in Episerver commerce items such as products and variants don&#39;t display the option for creating a new block, and only allows for blocks to be dragged in, as seen below.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/05dc75e7672e47a3ab04a91cef96cee2.aspx&quot; alt=&quot;Image content-area.PNG&quot; /&gt;&lt;/p&gt;
&lt;p&gt;However, an extremely simple solution to&amp;nbsp;change this default behaviour is to inherit from IResourceable on your product/variant which will require the interface member ContentAssetsID to be declared which can simply be scaffolded to false, and this will be all the code required to display the content area as expected!&amp;nbsp;&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;    public abstract class SiteProductContent : ProductContent, IResourceable
    {
        [ScaffoldColumn(false)]
        public Guid ContentAssetsID { get; set; }
    }&lt;/code&gt;&lt;/pre&gt;

&lt;/body&gt;
&lt;/html&gt;</description>            <guid>https://world.optimizely.com/blogs/david-harlow/dates/2018/3/extending-commerce---content-area-functionality/</guid>            <pubDate>Tue, 06 Mar 2018 10:24:28 GMT</pubDate>           <category>Blog post</category></item><item> <title>Extending Episerver Forms: Postcode Lookup Tool</title>            <link>https://world.optimizely.com/blogs/david-harlow/dates/2017/12/extending-episerver-forms-postcode-lookup-tool/</link>            <description>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;A common requirement from clients we have at &lt;a href=&quot;https://www.redweb.com/&quot;&gt;Redweb&lt;/a&gt; is the ability to extend Episerver forms to provide a postcode lookup tool, which is now an occurring component of any form requiring an address. Despite Episerver Forms providing a simplistic block-based approach to building a form, there is no native method for enabling the different elements to interact with one another.&lt;/p&gt;
&lt;p&gt;To create our postcode lookup form element, we built a view consisting of a text input for the postcode and a hidden dropdown to display the response of an asynchronous API request to a postcode lookup service. Once a dropdown value has been selected, the relevant input elements within that form will need populating with its respective data.&lt;/p&gt;
&lt;p&gt;To ensure that we populate the correct fields with the correct data, we built several mapping properties onto the form element that represent the different properties of the address that is returned by the postcode lookup service.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;    [ContentType(
        DisplayName = &quot;Postcode Address Lookup&quot;,
        GUID = &quot;{A4EE6053-3932-4300-8B3B-7BABF9AEAB67}&quot;,
        Order = 4000)]
    [AvailableValidatorTypes(Include = new Type[] { typeof(PostcodeValidator) })]
    public class PostcodeLookupElementBlock : ValidatableElementBlockBase
    {
        [Display(
            Name = &quot;Company Mapping&quot;,
            Description = &quot;Specify the element for the company input element&quot;,
            GroupName = PropertyGroupNames.Configuration,
            Order = 10
        )]
        [EditorDescriptor(EditorDescriptorType = typeof(FormPropertyEditorDescriptor))]
        public virtual string CompanyMapping { get; set; }

        [Display(
            Name = &quot;Building Number Mapping&quot;,
            Description = &quot;Specify the element for the building number input element&quot;,
            GroupName = PropertyGroupNames.Configuration,
            Order = 20
        )]
        [EditorDescriptor(EditorDescriptorType = typeof(FormPropertyEditorDescriptor))]
        public virtual string BuildingNoMapping { get; set; }

        [Display(
            Name = &quot;Address Line 1 Mapping&quot;,
            Description = &quot;Specify the element for the address line 1 input element&quot;,
            GroupName = PropertyGroupNames.Configuration,
            Order = 30
        )]
        [EditorDescriptor(EditorDescriptorType = typeof(FormPropertyEditorDescriptor))]
        public virtual string AddressLine1Mapping { get; set; }

        [Display(
            Name = &quot;Address Line 2 Mapping&quot;,
            Description = &quot;Specify the element for the address line 2 input element&quot;,
            GroupName = PropertyGroupNames.Configuration,
            Order = 40
        )]
        [EditorDescriptor(EditorDescriptorType = typeof(FormPropertyEditorDescriptor))]
        public virtual string AddressLine2Mapping { get; set; }

        [Display(
            Name = &quot;Address Line 3 Mapping&quot;,
            Description = &quot;Specify the element for the address line 3 input element&quot;,
            GroupName = PropertyGroupNames.Configuration,
            Order = 50
        )]
        [EditorDescriptor(EditorDescriptorType = typeof(FormPropertyEditorDescriptor))]
        public virtual string AddressLine3Mapping { get; set; }

        [Display(
            Name = &quot;Town Mapping&quot;,
            Description = &quot;Specify the element for the town input element&quot;,
            GroupName = PropertyGroupNames.Configuration,
            Order = 60
        )]
        [EditorDescriptor(EditorDescriptorType = typeof(FormPropertyEditorDescriptor))]
        public virtual string TownMapping { get; set; }

        [Display(
            Name = &quot;County Mapping&quot;,
            Description = &quot;Specify the element for the County input element&quot;,
            GroupName = PropertyGroupNames.Configuration,
            Order = 70
        )]
        [EditorDescriptor(EditorDescriptorType = typeof(FormPropertyEditorDescriptor))]
        public virtual string CountyMapping { get; set; }

        [Display(
            Name = &quot;Country Mapping&quot;,
            Description = &quot;Specify the element for the Country input element&quot;,
            GroupName = PropertyGroupNames.Configuration,
            Order = 80
        )]
        [EditorDescriptor(EditorDescriptorType = typeof(FormPropertyEditorDescriptor))]
        public virtual string CountryMapping { get; set; }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As can be seen, these properties use a custom editor descriptor attribute which utilises a selection factory to build a SelectItem object of all the names of all other elements within the current form so that the user can simply map the different parts of an address to their respective element block.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;    public class FormPropertySelectionFactory : ServiceBase, ISelectionFactory
    {
        private Injected&amp;lt;IContentRepository&amp;gt; ReadWriteContentService { get; set; }

        /// &amp;lt;summary&amp;gt;
        /// Gets the selections.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name=&quot;metadata&quot;&amp;gt;The metadata.&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
        public IEnumerable&amp;lt;ISelectItem&amp;gt; GetSelections(ExtendedMetadata metadata)
        {
            var fieldList = new List&amp;lt;SelectItem&amp;gt;();
            var form = metadata.FindOwnerContent().ParentLink;

            // Get all children properties of form that are text inputs
            var children = ReadWriteContentService.Service
                .GetChildren&amp;lt;ElementBlockBase&amp;gt;(form)
                .OfType&amp;lt;TextboxElementBlock&amp;gt;();

            foreach (var field in children)
            {
                fieldList.Add(new SelectItem { Value = field.FormElement.ElementName, Text = field.Label});
            }
            return fieldList;
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;    public class FormPropertyEditorDescriptor : EditorDescriptor
    {
        public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable&amp;lt;Attribute&amp;gt; attributes)
        {
            SelectionFactoryType = typeof(FormPropertySelectionFactory);
            ClientEditingClass = &quot;epi-cms/contentediting/editors/SelectionEditor&quot;;

            base.ModifyMetadata(metadata, attributes);
        }

    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ensuring that the value of the property selected represents a value that can be used to easily locate the separate form elements via a front-end framework, we can then populate these form elements with their respective data returned from the API request.&lt;/p&gt;
&lt;p&gt;Using this approach allows us to provide a customizable postcode lookup tool which enables the use of as many, or as few aspects of an address as required, whilst also retaining Episerver Form&amp;rsquo;s block-based structure.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/1a28d2e6fe7244a6a642ef873dcd718c.aspx&quot; alt=&quot;Image CMSpostcode.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/300b998e028d4cf9bedf246984854c11.aspx&quot; alt=&quot;Image postcode.png&quot; /&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</description>            <guid>https://world.optimizely.com/blogs/david-harlow/dates/2017/12/extending-episerver-forms-postcode-lookup-tool/</guid>            <pubDate>Thu, 21 Dec 2017 16:11:18 GMT</pubDate>           <category>Blog post</category></item></channel>
</rss>