<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sitecore Xperiences &#187; Experience Editor</title>
	<atom:link href="https://blog.peplau.com.br/category/experience-editor/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.peplau.com.br</link>
	<description>The things I&#039;ve seen as a Sitecore Professional</description>
	<lastBuildDate>Sun, 09 Mar 2025 21:54:22 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.41</generator>
	<item>
		<title>Custom Reset Layout in Content and Experience Editor Modes</title>
		<link>https://blog.peplau.com.br/custom-reset-layout-in-content-and-experience-editor-modes/</link>
		<comments>https://blog.peplau.com.br/custom-reset-layout-in-content-and-experience-editor-modes/#comments</comments>
		<pubDate>Fri, 09 Feb 2018 00:04:51 +0000</pubDate>
		<dc:creator><![CDATA[Rodrigo Peplau]]></dc:creator>
				<category><![CDATA[Content Edition Experience]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Experience Editor]]></category>

		<guid isPermaLink="false">http://blog.peplau.com.br/?p=728</guid>
		<description><![CDATA[<div class="lr_horizontal_share" data-share-url="https://blog.peplau.com.br/custom-reset-layout-in-content-and-experience-editor-modes/"></div>Recently I had to customize the code that triggers when a Reset Layout is executed. If you ever had to attach any code to it, this post is for you! You know, that sympathetic prompt: The first thing you need to know is that Content Editor and Experience Editor does that differently, so let&#8217;s go for them: Round 1 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Recently I had to customize the code that triggers when a Reset Layout is executed. If you ever had to attach any code to it, this post is for you!</p>
<p>You know, that sympathetic prompt:</p>
<p><a href="http://blog.peplau.com.br/wp-content/uploads/Reset-Layout-Prompt.png"><img class="alignnone size-full wp-image-730" src="http://blog.peplau.com.br/wp-content/uploads/Reset-Layout-Prompt.png" alt="Reset Layout Prompt" width="372" height="331" /></a></p>
<p>The first thing you need to know is that Content Editor and Experience Editor does that differently, so let&#8217;s go for them:</p>
<h2>Round 1 &#8211; Content Editor</h2>
<p>Content Editor uses a command for that (pagedesigner:reset), which is natively implemented by the class <em>Sitecore.Shell.Applications.Layouts.PageDesigner.Commands.Reset</em>. We first need to create a class that will inherit from the original, so we don&#8217;t lose the original behavior, and implement our custom logic on it.</p>
<p>Create a Command class like this:</p>
<pre>using System.Web.Mvc;
using Sitecore.Shell.Applications.Dialogs.ResetLayout;
using Sitecore.Web.UI.Sheer;

namespace MyProject.Commands
{
    public class ResetLayoutCommand : Sitecore.Shell.Applications.Layouts.PageDesigner.Commands.Reset
    {
        protected override void Run(ClientPipelineArgs args)
        {
            // Runs the default behaviour
            base.Run(args);

            // Skips if the Reset Layout prompt is not submited or results is undefined
            if (!args.IsPostBack || string.IsNullOrEmpty(args.Result) || args.Result == "undefined")
                return;

            // Takes the item that has been reset
            var itemReset = DeserializeItems(args.Parameters["items"])[0];

            // And here is where your custom logic will be implemented
            // .....
        }
    }
}</pre>
<p>Then we override the default command with our class in a config patch like this:</p>
<pre>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"&gt;
    &lt;sitecore&gt;
        &lt;commands&gt;
            &lt;command patch:instead="*[@name='pagedesigner:reset']" name="pagedesigner:reset" resolve="true" 
                type="MyProject.Commands.ResetLayoutCommand, MyProject"/&gt;
        &lt;/commands&gt;
    &lt;/sitecore&gt;
&lt;/configuration&gt;</pre>
<p>And this is how we run the first leg. But it is not over yet, let&#8217;s go for&#8230;</p>
<h2>Round 2 &#8211; Experience Editor</h2>
<p>Experience Editor, on the other hand, uses a different approach for that. It has a request node named &#8220;<em>ExperienceEditor.</em>ResetLayout<em>.Execute</em>&#8221; under <em>&lt;sitecore.experienceeditor.speak.requests&gt;</em> that we need to replace. This request node is implemented by the native class <em>Sitecore.ExperienceEditor.Speak.Ribbon.Requests.</em>ResetLayout<em>.Execute</em>, which again we are going to inherit.</p>
<p>So our Request class will be like this:</p>
<pre>using System;
using System.Web.Mvc;
using Sitecore.Diagnostics;
using Sitecore.ExperienceEditor.Speak.Attributes;
using Sitecore.ExperienceEditor.Speak.Server.Responses;
using Sitecore.Shell.Applications.Dialogs.ResetLayout;

namespace MyProject.ExperienceEditor
{
    public class ResetLayout : Sitecore.ExperienceEditor.Speak.Ribbon.Requests.ResetLayout.Execute
    {
        [HasItemPermissions(Id = "{BE98D7F0-7404-4F97-8E4C-8FEF4ACA5DA3}", Path = "/sitecore/content/Applications/WebEdit/Ribbons/WebEdit/Advanced/Layout/Reset")]
        public override PipelineProcessorResponseValue ProcessRequest()
        {
            // Instantiates the returning object and 
            var processorResponseValue = new PipelineProcessorResponseValue();

            try
            {
                // Executes the default RESET LAYOUT process
                processorResponseValue = base.ProcessRequest();

                // Takes the item that has been reset
                var itemReset = RequestContext.Item;

                // And here is where your custom logic will be implemented
                // ..... (OF COURSE, DON'T DUPLICATE YOUR LOGIC!)
            }
            catch (Exception e)
            {
                Log.Error(
                    $"[ResetLayout] Cannot execute post Layout Reset operations to item '{RequestContext.Item.Paths.Path}'", e, GetType());
            }
            return processorResponseValue;
        }
    }
}</pre>
<p>And finally we patch it again with a config file like this:</p>
<pre>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"&gt;
    &lt;sitecore&gt;
        &lt;sitecore.experienceeditor.speak.requests&gt;
            &lt;request patch:instead="*[@name='ExperienceEditor.ResetLayout.Execute']"
                name="ExperienceEditor.ResetLayout.Execute"
                type="MyProject.ExperienceEditor.ResetLayout, MyProject" /&gt;
        &lt;/sitecore.experienceeditor.speak.requests&gt;
    &lt;/sitecore&gt;
&lt;/configuration&gt;</pre>
<p>And that&#8217;s all&#8230; You now have your custom code being triggered by both Content Editor and Experience Editor!</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.peplau.com.br/custom-reset-layout-in-content-and-experience-editor-modes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sitecore 9 Update 1 - Bug saving Shared Layout in Experience Editor</title>
		<link>https://blog.peplau.com.br/sitecore-9-update-1-bug-saving-shared-layout-in-experience-editor/</link>
		<comments>https://blog.peplau.com.br/sitecore-9-update-1-bug-saving-shared-layout-in-experience-editor/#comments</comments>
		<pubDate>Thu, 01 Feb 2018 14:08:19 +0000</pubDate>
		<dc:creator><![CDATA[Rodrigo Peplau]]></dc:creator>
				<category><![CDATA[Bug fixing]]></category>
		<category><![CDATA[Experience Editor]]></category>
		<category><![CDATA[Support Ticket]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.peplau.com.br/?p=717</guid>
		<description><![CDATA[<div class="lr_horizontal_share" data-share-url="https://blog.peplau.com.br/sitecore-9-update-1-bug-saving-shared-layout-in-experience-editor/"></div>A few weeks ago, while upgrading one of at Nish Tech&#8217;s early-stages projects into Sitecore 9 Update 1, a very strange behavior when you try to do a very simple task: edit a Shared Layout of a page in Experience Editor. When you try to do that, the infamous screen &#8220;Layout not Set&#8221; shows right [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>A few weeks ago, while upgrading one of at Nish Tech&#8217;s early-stages projects into Sitecore 9 Update 1, a very strange behavior when you try to do a very simple task: edit a Shared Layout of a page in Experience Editor.</p>
<p>When you try to do that, the infamous screen &#8220;Layout not Set&#8221; shows right after saving.</p>
<p><a href="http://blog.peplau.com.br/wp-content/uploads/Sitecore-9-Bug.png"><img class="alignnone wp-image-719 size-full" src="http://blog.peplau.com.br/wp-content/uploads/Sitecore-9-Bug.png" alt="Sitecore 9 Bug" width="1544" height="800" /></a></p>
<p>Initially, I observed that when saving in a _Standard Values, but later I noticed it can also happen with ordinary items. If you want to see how to reproduce the error, check <a title="SC9U1 Save Shared Layout in Experience Editor in a Standard Values" href="http://blog.peplau.com.br/wp-content/uploads/SC9U1-Save-Shared-Layout-in-Experience-Editor-in-a-Standard-Values.avi" target="_blank">this video</a>.</p>
<p>Interesting enough, when you look at your <em>Layout</em> and <em>Final Layout</em> fields in Raw mode, you notice that the Shared Layout has a value such as:</p>
<blockquote><p><em>&lt;r xmlns:p=&#8221;p&#8221; xmlns:s=&#8221;s&#8221; p:p=&#8221;1&#8243;&gt;&lt;d id=&#8221;{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}&#8221;&gt;&lt;r uid=&#8221;{597C17AD-DEF3-4947-BE5B-4104A2143F17}&#8221; p:after=&#8221;*[1=2]&#8221; s:id=&#8221;{493B3A83-0FA7-4484-8FC9-4680991CF743}&#8221; s:ph=&#8221;/main/centercolumn/content&#8221; /&gt;&lt;/d&gt;&lt;/r&gt;</em></p></blockquote>
<p>Which seems to have a more appropriate syntax to be in the <em>Final Layout</em> field instead, as you can check if you match this against the original value:</p>
<blockquote><p><em>&lt;r xmlns:xsd=&#8221;http://www.w3.org/2001/XMLSchema&#8221;&gt;&lt;d id=&#8221;{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}&#8221; l=&#8221;{14030E9F-CE92-49C6-AD87-7D49B50E42EA}&#8221;&gt;&lt;r ds=&#8221;&#8221; id=&#8221;{885B8314-7D8C-4CBB-8000-01421EA8F406}&#8221; par=&#8221;&#8221; ph=&#8221;main&#8221; uid=&#8221;{43222D12-08C9-453B-AE96-D406EBB95126}&#8221; /&gt;&lt;r ds=&#8221;&#8221; id=&#8221;{CE4ADCFB-7990-4980-83FB-A00C1E3673DB}&#8221; par=&#8221;&#8221; ph=&#8221;/main/centercolumn&#8221; uid=&#8221;{CF044AD9-0332-407A-ABDE-587214A2C808}&#8221; /&gt;&lt;r ds=&#8221;&#8221; id=&#8221;{493B3A83-0FA7-4484-8FC9-4680991CF743}&#8221; par=&#8221;&#8221; ph=&#8221;/main/centercolumn/content&#8221; uid=&#8221;{B343725A-3A93-446E-A9C8-3A2CBD3DB489}&#8221; /&gt;&lt;/d&gt;&lt;d id=&#8221;{46D2F427-4CE5-4E1F-BA10-EF3636F43534}&#8221; l=&#8221;{14030E9F-CE92-49C6-AD87-7D49B50E42EA}&#8221;&gt;&lt;r ds=&#8221;&#8221; id=&#8221;{493B3A83-0FA7-4484-8FC9-4680991CF743}&#8221; par=&#8221;&#8221; ph=&#8221;content&#8221; uid=&#8221;{A08C9132-DBD1-474F-A2CA-6CA26A4AA650}&#8221; /&gt;&lt;/d&gt;&lt;/r&gt;</em></p></blockquote>
<h2>Sitecore Helpdesk heroes</h2>
<p>Then I reported the issue to our amazing Sitecore Helpdesk, who after a couple weeks came out with a bugfix, that now I want to share with our Sitecore Community.</p>
<p>I would like to thank the whole gang of superheroes at Sitecore Helpdesk, for providing this good HotFix in a proper time and allowing me to share it, in special to <b id="aui-3-18-0-4_4908">Igor Denisenko</b>, <b id="aui-3-18-0-4_4908"><b id="aui-3-18-0-4_4929">Pavel Ivashchenko </b></b>and <b id="aui-3-18-0-4_4908"><b id="aui-3-18-0-4_4929"><b id="aui-3-18-0-4_4937">Ielyzaveta Kalinchuk</b></b></b>,<b id="aui-3-18-0-4_4908"><b id="aui-3-18-0-4_4929"><b id="aui-3-18-0-4_4937"> </b></b></b>the good guys who replied to my ticket. You are awesome, mates!</p>
<h2>The cure: HotFix 203387</h2>
<p>You can find the hotfix at <a href="http://dl.sitecore.net/hotfix/SC%20Hotfix-203387-1%20Sitecore.ExperienceEditor%204.1.1.zip">this link</a>.</p>
<ul>
<li>Please be aware that the hotfix was built <strong>specifically for Sitecore XP 9.0 rev. 171219 (Update-1)!</strong> You should not install it on other Sitecore versions or in combination with other hotfixes unless explicitly instructed by Sitecore Support;</li>
<li>Note that you need to extract ZIP file contents to locate installation instructions and related files inside it.</li>
</ul>
<p>If you have anything to add on this, please drop a comment and let me know!</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.peplau.com.br/sitecore-9-update-1-bug-saving-shared-layout-in-experience-editor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://blog.peplau.com.br/wp-content/uploads/SC9U1-Save-Shared-Layout-in-Experience-Editor-in-a-Standard-Values.avi" length="1083148" type="video/avi" />
		</item>
		<item>
		<title>Site-specific RichText Editor Profiles - custom Source in native RichText fields</title>
		<link>https://blog.peplau.com.br/site-specific-richtext-editor-profiles-custom-source-in-native-richtext-fields/</link>
		<comments>https://blog.peplau.com.br/site-specific-richtext-editor-profiles-custom-source-in-native-richtext-fields/#comments</comments>
		<pubDate>Sat, 06 Jan 2018 13:42:31 +0000</pubDate>
		<dc:creator><![CDATA[Rodrigo Peplau]]></dc:creator>
				<category><![CDATA[Content Edition Experience]]></category>
		<category><![CDATA[Experience Editor]]></category>
		<category><![CDATA[Richtext Editor]]></category>

		<guid isPermaLink="false">http://blog.peplau.com.br/?p=665</guid>
		<description><![CDATA[<div class="lr_horizontal_share" data-share-url="https://blog.peplau.com.br/site-specific-richtext-editor-profiles-custom-source-in-native-richtext-fields/"></div>Everybody knows how to select different Editor Profiles using the Source property in a Rich Text field. Out of the box, you can only pass a hardcoded path to the Editor Profile, making the template totally linked to one and only one Profile. Hardcoded??? But what if we could make this dynamic and site-specific? That way, the same template could present different Editor Profiles [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Everybody knows how to select different Editor Profiles using the Source property in a Rich Text field. Out of the box, you can only pass a hardcoded path to the Editor Profile, making the template totally linked to one and only one Profile.</p>
<p><a href="http://blog.peplau.com.br/wp-content/uploads/Rich-Text-Source-property.png"><img class="alignnone size-full wp-image-666" src="http://blog.peplau.com.br/wp-content/uploads/Rich-Text-Source-property.png" alt="Rich Text Source property" width="1174" height="176" /></a></p>
<h2>Hardcoded???</h2>
<p>But what if we could make this dynamic and site-specific? That way, the same template could present different Editor Profiles for different websites.</p>
<p>Something like this:</p>
<p><a href="http://blog.peplau.com.br/wp-content/uploads/Rich-Text-Site-specific-Source-property.png"><img class="alignnone size-full wp-image-667" src="http://blog.peplau.com.br/wp-content/uploads/Rich-Text-Site-specific-Source-property.png" alt="Rich Text Site-specific Source property" width="703" height="172" /></a></p>
<p>Then at each of your websites you can have your own Source definition item:</p>
<p><a href="http://blog.peplau.com.br/wp-content/uploads/Site-Specific-RichText-Editor-Source.png"><img class="alignnone size-full wp-image-668" src="http://blog.peplau.com.br/wp-content/uploads/Site-Specific-RichText-Editor-Source.png" alt="Site-Specific RichText Editor Source" width="775" height="271" /></a></p>
<p>Cool?</p>
<h2>Site-specific field Sources</h2>
<p>If you ever happen to play with Habitat you might have noticed it has a <a href="https://github.com/Sitecore/Habitat/tree/master/src/Foundation/Multisite/code" target="_blank">Multisite Module</a>, that implements something similar for Component&#8217;s Datasources. My solution is based on that, working perfectly with Droplists and other listing fields.</p>
<h2>Not so fast&#8230;</h2>
<p>But unfortunately, it doesn&#8217;t work with the RichText field since it is attached to the &#8220;&lt;getLookupSourceItems&gt;&#8221; pipeline. The RichText field has a different implementation which does not trigger this pipeline.</p>
<h2>Custom Source for Rich Text fields!</h2>
<p>So how can this be customized? After a long web research and decompiling Sitecore DLLs, here is what I came out.</p>
<p>If you take a look at the Field item definition under <em>core:/sitecore/system/Field types/Simple Types/Rich Text</em> you will notice it has the following content at the Control field:</p>
<p><a href="http://blog.peplau.com.br/wp-content/uploads/Rich-Text-definition-item.png"><img class="alignnone size-full wp-image-669" src="http://blog.peplau.com.br/wp-content/uploads/Rich-Text-definition-item.png" alt="Rich Text definition item" width="408" height="91" /></a></p>
<p>I found out that this is similar to how a Command is registered, however no such a Command called &#8220;content:RichText&#8221; exists anywhere at my Sitecore configs. This is actually registered by the following config entry:</p>
<pre class="line"><span class="html-tag">&lt;controlSources&gt;
</span>    &lt;source<span class="html-attribute"> <span class="html-attribute-name">assembly</span>="<span class="html-attribute-value">Sitecore.Kernel</span>"</span><span class="html-attribute"> <span class="html-attribute-name">namespace</span>="<span class="html-attribute-value">Sitecore.Shell.Applications.ContentEditor</span>"</span><span class="html-attribute"> <span class="html-attribute-name">prefix</span>="<span class="html-attribute-value">content</span>"</span><span class="html-attribute"> <span class="html-attribute-name">mode</span>="<span class="html-attribute-value">on</span>"</span>/&gt;</pre>
<p class="collapsible-content">The secret here is the <em>prefix=&#8221;content&#8221;</em> which is used as the basis to register the whole namespace, taking classes dynamically by its name (&#8220;RichText&#8221; in this case).</p>
<h3 class="collapsible-content">Step 1 &#8211; Extend native class</h3>
<p class="collapsible-content">Create your class that extends the Rich Text field &#8211; we will inherit from the original &#8220;<em>Sitecore.Shell.Applications.ContentEditor.RichText</em>&#8221; and only overwrite the Source property. Notice that I am re-using the same code used at my &lt;getLookupSourceItems&gt; to apply the same logic to the Rich Text field.</p>
<pre>using Sitecore.Diagnostics;
using Sitecore.Pipelines.GetLookupSourceItems;
using Website.Core.Multisite.Pipelines;
namespace Website.Core.Fields
{
   public class RichText : Sitecore.Shell.Applications.ContentEditor.RichText
   {
     /// &lt;summary&gt;Gets or sets the source.&lt;/summary&gt;
     /// &lt;value&gt;The source.&lt;/value&gt;
     public new string Source
     {
       get { return GetViewStateString(nameof(Source)); }
       set
       {
         Assert.ArgumentNotNull(value, nameof(value));
<strong>         // Reuse the same Pipeline implementation here as at my &lt;getLookupSourceItems&gt; pipeline
</strong><strong>         var processor = new LookupItemsFromField();
</strong><strong>         var args = new GetLookupSourceItemsArgs()
</strong><strong>         {
</strong><strong>           Source = value,
</strong><strong>           Item = Sitecore.Context.ContentDatabase.GetItem(ItemID)
</strong><strong>         };
</strong><strong>         processor.Process(args);
</strong><strong>         value = args.Source;
</strong>         SetViewStateString(nameof(Source), value);
       }
    }
  }
}</pre>
<h3 class="collapsible-content">Step 2 &#8211; Patch Sitecore to use our custom class</h3>
<p class="collapsible-content">Now we need to patch Sitecore. Our custom class needs to be registered BEFORE the native one so it can assume its place.</p>
<pre>&lt;?xml version="1.0"?&gt;
  &lt;configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"&gt;
    &lt;sitecore&gt;
      &lt;controlSources&gt;
        &lt;source patch:before="source[@namespace='Sitecore.Shell.Applications.ContentEditor']" mode="on" namespace="Website.Core.Fields" assembly="Website.Core" prefix="content"/&gt;
      &lt;/controlSources&gt;
    &lt;/sitecore&gt;
&lt;/configuration&gt;</pre>
<p class="collapsible-content">Now that you can intercept the native RichText implementation, you can implement your own logic for Source resolving!</p>
<p class="collapsible-content">You know a better way of doing this? Please let me know!</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.peplau.com.br/site-specific-richtext-editor-profiles-custom-source-in-native-richtext-fields/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Prevent orphan components in Experience Editor when deleting composed components</title>
		<link>https://blog.peplau.com.br/prevent-a-component-to-be-deleted-in-experience-editor-when-it-has-inner-components/</link>
		<comments>https://blog.peplau.com.br/prevent-a-component-to-be-deleted-in-experience-editor-when-it-has-inner-components/#comments</comments>
		<pubDate>Fri, 29 Sep 2017 22:44:45 +0000</pubDate>
		<dc:creator><![CDATA[Rodrigo Peplau]]></dc:creator>
				<category><![CDATA[Content Edition Experience]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Experience Editor]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.peplau.com.br/?p=617</guid>
		<description><![CDATA[<div class="lr_horizontal_share" data-share-url="https://blog.peplau.com.br/prevent-a-component-to-be-deleted-in-experience-editor-when-it-has-inner-components/"></div>If an editor deletes a component in Experience Editor and that component has inner components, only the outer component will be actually deleted from the page rendering. Inner components will not show anymore (and often Content Editors will be happy), so why would that be a problem? The problem Take for instance this set of renderings [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>If an editor deletes a component in Experience Editor and that component has inner components, only the outer component will be actually deleted from the page rendering. Inner components will not show anymore (and often Content Editors will be happy), so why would that be a problem?</p>
<h2>The problem</h2>
<p>Take for instance this set of renderings of a certain page:</p>
<p><a href="http://blog.peplau.com.br/wp-content/uploads/Orphan-Renderings-before.png"><img class="alignnone wp-image-619 size-full" src="http://blog.peplau.com.br/wp-content/uploads/Orphan-Renderings-before.png" alt="Orphan Renderings-before" width="762" height="135" /></a></p>
<p>If in Experience Editor someone tries to delete it:</p>
<p><a href="http://blog.peplau.com.br/wp-content/uploads/Remove-Components.png"><img class="alignnone size-full wp-image-620" src="http://blog.peplau.com.br/wp-content/uploads/Remove-Components.png" alt="Remove Components" width="261" height="108" /></a></p>
<p>The result will be a &#8220;ghost&#8221; orphan item, which will not render when the page loads because its placeholder does not exist anymore.</p>
<p><a href="http://blog.peplau.com.br/wp-content/uploads/Orphan-Renderings-after.png"><img class="alignnone size-full wp-image-621" src="http://blog.peplau.com.br/wp-content/uploads/Orphan-Renderings-after.png" alt="Orphan Renderings-after" width="746" height="102" /></a></p>
<p>That rendering will continue at the page rendering, being either forgotten forever or re-appearing when someone tries to add a new Carousel to the same Full-Width Container placeholder.</p>
<h2>Not just me</h2>
<p>I&#8217;ve seen more people concerned with that &#8211; such as the author of <a href="https://sitecore.stackexchange.com/questions/4094/remove-child-renderings-from-layout" target="_blank">this question at Sitecore Exchange</a> &#8211; and some other people suggested possible solutions.</p>
<p>One approach I tried was to follow <a href="https://blog.horizontalintegration.com/2015/10/09/sitecore-orphan-children-after-parent-component-removal/" target="_blank">this blog post by Mike Tschida</a> and implement a pipeline processor to clean-up the Page Rendering, removing orphan components when the page is saved. That would be perfect, however during development or debugging, it is very common to temporarily move a component to an unexistent placeholder to make it vanish from the page. In cases like that, the component would be deleted, which is not desired.</p>
<h2>Acting at the other end</h2>
<p>So what if, instead of acting later at the server, we stop content editors at the root of the problem: the Experience Editor? At that case, when an editor attempts to delete a component which has inner components, a prompt like this would be displayed. In order to delete the outer component, the editor now needs to delete the inner components first.</p>
<p><a href="http://blog.peplau.com.br/wp-content/uploads/Orphan-Renderings-prompt.png"><img class="alignnone size-full wp-image-622" src="http://blog.peplau.com.br/wp-content/uploads/Orphan-Renderings-prompt.png" alt="Orphan Renderings-prompt" width="307" height="146" /></a></p>
<p>Inspired by <a href="https://stackoverflow.com/questions/38634701/delete-confirmation-when-deleting-from-floating-menu-in-a-page-editor-in-sitecor" target="_blank">this simple Stack Overflow post</a>,  in which the author was looking for a way to simply ask for a confirmation before deleting a component, I ended up with the solution below.</p>
<h2>Nip the evil in the bud</h2>
<p>The deletion of a component is handled by javascript code located at \sitecore\shell\Applications\Page Modes\ChromeTypes\RenderingChromeType.js &#8211; more specifically at the deleteControl method. Our fix will comment out the original code (I will leave there for future reference in case of an upgrade) and add the following code:</p>
<pre>    deleteControl: function () {
        var canDelete = this.canDeleteControl(this.chrome);
        if (canDelete === false) {
            alert("Please delete inner controls before deleting this.");
            return false;
        }
        var placeholder = this.getPlaceholder();
        if (placeholder) {
            placeholder.type.deleteControl(this.chrome);
            return true;
        }
        return false;
    },
</pre>
<p>Along of course with the new canDeleteControl method, which does the trick of verifying if the component attempted to be deleted has inner components.</p>
<pre>    canDeleteControl: function (chrome) {
        var canDelete = true;
        var childChromes = chrome.getChildChromes();
        for (var i = 0; i &lt; childChromes.length; i++) {
            if (childChromes[i].type.key() == "placeholder") {
                canDelete = this.canDeleteControl(childChromes[i]);
                if (canDelete === false)
                    break;
            }
            else if (childChromes[i].type.key() == "rendering") {
                canDelete = false;
                break;
            }
        }
        return canDelete;
    },
</pre>
<p>And that&#8217;s all we need! Replace this file in all instances, clean up your browser caches and don&#8217;t worry about orphan components anymore!</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.peplau.com.br/prevent-a-component-to-be-deleted-in-experience-editor-when-it-has-inner-components/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Advanced display of SVG Images in Sitecore</title>
		<link>https://blog.peplau.com.br/advanced-display-of-svg-images-in-sitecore/</link>
		<comments>https://blog.peplau.com.br/advanced-display-of-svg-images-in-sitecore/#comments</comments>
		<pubDate>Fri, 31 Jul 2015 23:56:39 +0000</pubDate>
		<dc:creator><![CDATA[Rodrigo Peplau]]></dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Experience Editor]]></category>
		<category><![CDATA[Front-end]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.peplau.com.br/?p=219</guid>
		<description><![CDATA[<div class="lr_horizontal_share" data-share-url="https://blog.peplau.com.br/advanced-display-of-svg-images-in-sitecore/"></div>SVG Images are basically vector images (coordinates, objects and properties) with data that can be manipulated with CSS styling &#8211; check out this article for details on how that works. In short, to take advantage of CSS styling over SVG files, you must throw the XML content of the SVG file, directly into the HTML markup. So instead of the traditional [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>SVG Images are basically vector images (coordinates, objects and properties) with data that can be manipulated with CSS styling &#8211; check out <a href="https://css-tricks.com/using-svg/" target="_blank">this article</a> for details on how that works.</p>
<p>In short, to take advantage of CSS styling over SVG files, you must throw the XML content of the SVG file, directly into the HTML markup. So instead of the traditional &lt;img tag:</p>
<pre>&lt;img src="image.svg"</pre>
<p>You must throw inline the content of the SVG file, which will be something like:</p>
<pre>&lt;svg ...&gt; &lt;ellipse class="chair" .../&gt; <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>svg</span><span class="token punctuation">&gt;</span></span></pre>
<p>In Sitecore that means you can&#8217;t use the standard <strong>sc:Image</strong> control to render the content of an Image Field &#8211; that will render your SVG as an &lt;img HTML tag, which can&#8217;t be touched by CSS styling&#8230;</p>
<p><strong>Usercontrol</strong></p>
<p>In order to have something that is compatible both with CSS Styling and Sitecore&#8217;s Page Editor mode, my proposal is to have a custom asp usercontrol like this:</p>
<p><em><strong>Image.ascx</strong></em></p>
<pre>&lt;%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Image.ascx.cs" Inherits="Layouts.UserControls.Image" %&gt;
&lt;sc:Image runat="server" ID="scImage" /&gt;
&lt;asp:Literal runat="server" ID="litImage"&gt;&lt;/asp:Literal&gt;</pre>
<p><em><strong> Image.ascx.cs (Codebehind)</strong></em></p>
<pre>namespace Layouts.UserControls
{
 public partial class Image : UserControl
 {
   /// &lt;summary&gt;
   /// Component's Field
   /// &lt;/summary&gt;
   public string Field { get; set; }</pre>
<pre>   /// &lt;summary&gt;
   /// Component's Item (Default=Context)
   /// &lt;/summary&gt;
   public Item Item
   {
      get { return _item ?? Sitecore.Context.Item; }
      set { _item = value; }
   }
   private Item _item;</pre>
<pre>   protected void Page_Load(object sender, EventArgs e)
   {
     // When editing in Page Editor mode, always use an &lt;sc:image
     // If no field is set, escape and let it break
     if (Sitecore.Context.PageMode.IsPageEditorEditing || string.IsNullOrEmpty(Field))
     {
        ShowScImage();
        return;
     }</pre>
<pre>     // Escape if field is not found
     var referencedImageField = (Sitecore.Data.Fields.ImageField)Item.Fields[Field];
     if (referencedImageField == null)
     {
       ShowScImage();
       return;
     }</pre>
<pre>     // Get referenced image - Scape if image is not found
     var imageItem = referencedImageField.MediaItem;
     if (imageItem == null)
     {
        ShowScImage();
        return;
     }</pre>
<pre>     // If this is not an svg use a normal &lt;sc:Image
     var imageMediaItem = (MediaItem) imageItem;
     if (!imageMediaItem.Extension.ToLower().Contains("svg"))
     {
        ShowScImage();
        return;
     }</pre>
<pre>     ShowSvgImage(imageMediaItem);
 }</pre>
<pre> public static string GetMediaUrlWithServer(MediaItem mediaItem, Item item = null)
 {
    item = item ?? Sitecore.Context.Item;
    var options = new UrlOptions { AlwaysIncludeServerUrl = true, AddAspxExtension = false };
    var itemUrl = LinkManager.GetItemUrl(item, options);
    var mediaOptions = new MediaUrlOptions { AbsolutePath = true };
    var mediaUrl = MediaManager.GetMediaUrl(mediaItem, mediaOptions);
    return itemUrl + mediaUrl;
 }</pre>
<pre> private void ShowSvgImage(MediaItem mediaItem)
 {
    litImage.Visible = true;
    scImage.Visible = false;</pre>
<pre>    // Get string from Image Stream
    var stream = mediaItem.GetMediaStream();
    var reader = new StreamReader(stream);
    var svgString = reader.ReadToEnd();
    reader.Close();
    stream.Close();</pre>
<pre>    // Get SVG tag from string</pre>
<pre>    // No SVG tag found - fallback to &lt;sc:Image
    if (!svgString.Contains("&lt;svg"))
    {
       ShowScImage();
       return;
    }</pre>
<pre>    svgString = svgString.Substring(svgString.IndexOf("&lt;svg",StringComparison.Ordinal));
    litImage.Text = svgString;
 }</pre>
<pre> private void ShowScImage()
 {
    litImage.Visible = false;
    scImage.Visible = true;</pre>
<pre>    scImage.Item = Item;
    scImage.Field = Field;
    ReflectAttributesToControl(scImage); 
 }</pre>
<pre> private void ReflectAttributesToControl(WebControl control)
 {
    foreach (string key in Attributes.Keys)
     control.Attributes[key] = Attributes[key];
 }
}</pre>
<p><strong>Streaming</strong></p>
<p>The proposed solution makes use of Streaming for better performance, so rendering times are not affected.</p>
<p><strong>How to Use</strong></p>
<p>Now we have our custom image rendering control that renders inline SVG images when you are in Preview or Normal mode, and is compatible with Sitecore&#8217;s Page Editor mode.</p>
<p>To use, first you have to register the Usercontrol:</p>
<pre>&lt;%@ Register TagPrefix="custom" TagName="Image" Src="~/layouts/UserControls/Image.ascx" %&gt;</pre>
<p>Then use it just like you&#8217;d do with a standard sc:Image control:</p>
<pre>&lt;custom:Image runat="server" ID="imgSvgImage" Field="My Field Name" /&gt;</pre>
<p>At the code behind you can also access the properties &#8220;Field&#8221; and &#8220;Item&#8221; just like the normal Image control:</p>
<pre>imgClear.Item = Sitecore.Context.Item;</pre>
<p>And that&#8217;s all!</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.peplau.com.br/advanced-display-of-svg-images-in-sitecore/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
