SaaS CMS has officially launched! Learn more now.

Cannot modify TinyMCEConfiguration by implement ExtendedXhtmlStringEditorDescriptor

Vote:
 

Hi,

I want to extend XhtmlStringEditorDescriptor follow below code with purpose to get theme value from startpage and it throw error. How can I solve this?

[EditorDescriptorRegistration(TargetType = typeof(XhtmlString))]
    public class ExtendedXhtmlStringEditorDescriptor : XhtmlStringEditorDescriptor
    {
        private readonly ServiceAccessor<TinyMceConfiguration> _tinyMceConfiguration;
        private readonly IContentRepository _contentRepository;

        public ExtendedXhtmlStringEditorDescriptor(ServiceAccessor<TinyMceConfiguration> tinyMceConfiguration, IContentRepository contentRepository) : base(tinyMceConfiguration)
        {
            _tinyMceConfiguration = tinyMceConfiguration;
            _contentRepository = contentRepository;
        }

        public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes)
        {
            base.ModifyMetadata(metadata, attributes);
            var settings = metadata.EditorConfiguration["settings"] as TinyMceSettings;

            if (settings != null)
            {
                var startPage = _contentRepository.Get<StartPage>(SiteDefinition.Current.StartPage);
                settings.BodyClass(startPage.Theme.ToString());
            }
            metadata.EditorConfiguration["settings"] = settings;
        }
    }

#205106
Jun 28, 2019 14:04
Vote:
 

Hi,

I suspect the issue is that your editordescriptor is registered in addition to the default XhtmlStringEditorDescriptor so, when you call

base.ModifyMetadata(metadata, attributes);

the settings that adds have already been added and hence throw an error when it attempts to add them again. Unless you need to explicitly call "base.ModifyMetadata" I'd try removing that line.

#205110
Jun 28, 2019 14:33
Vote:
 

I've already try that before. Look like this one

[EditorDescriptorRegistration(TargetType = typeof(XhtmlString))]
    public class ExtendedXhtmlStringEditorDescriptor : XhtmlStringEditorDescriptor
    {
        private readonly ServiceAccessor<TinyMceConfiguration> _tinyMceConfiguration;
        private readonly IContentRepository _contentRepository;

        public ExtendedXhtmlStringEditorDescriptor(ServiceAccessor<TinyMceConfiguration> tinyMceConfiguration, IContentRepository contentRepository) : base(tinyMceConfiguration)
        {
            _tinyMceConfiguration = tinyMceConfiguration;
            _contentRepository = contentRepository;
        }

        public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes)
        {
            var settings = _tinyMceConfiguration.Invoke().Default();
            
            if (settings != null)
            {
                var startPage = _contentRepository.Get<StartPage>(SiteDefinition.Current.StartPage);
                settings.BodyClass(startPage.Theme.ToString());
            }
            if (metadata.EditorConfiguration.ContainsKey("settings"))
            {
                metadata.EditorConfiguration["settings"] = settings;
            }
            else
            {
                metadata.EditorConfiguration.Add("settings", settings);
            }
        }
    }

Edit mode of page cannot be rendered. And throw same error.

#205164
Jul 01, 2019 11:05
Vote:
 

Hmm. Interesting. I've just tried out a slightly simplified version of that code (hard-coding the body class rather than reading it from the start page) on an alloy site and it worked as expected, adding the css class to the editor. If you debug the code, which line is throwing the error?

The code I used is below:

[EditorDescriptorRegistration(TargetType = typeof(XhtmlString))]
public class ExtendedXhtmlStringEditorDescriptor : XhtmlStringEditorDescriptor
{
    private readonly ServiceAccessor<TinyMceConfiguration> _tinyMceConfiguration;
    private readonly IContentRepository _contentRepository;

    public ExtendedXhtmlStringEditorDescriptor(ServiceAccessor<TinyMceConfiguration> tinyMceConfiguration, IContentRepository contentRepository) : base(tinyMceConfiguration)
    {
        _tinyMceConfiguration = tinyMceConfiguration;
        _contentRepository = contentRepository;
    }

    public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes)
    {
        var settings = _tinyMceConfiguration.Invoke().Default();

        if (settings != null)
        {
            settings.BodyClass("blah");
        }
        if (metadata.EditorConfiguration.ContainsKey("settings"))
        {
            metadata.EditorConfiguration["settings"] = settings;
        }
        else
        {
            metadata.EditorConfiguration.Add("settings", settings);
        }
    }
}
#205167
Jul 01, 2019 13:31
Vote:
 

It is interesting, I try to hard code body class like you did but all properties in Edit mode won't render and still throw error. Fun thing is that when I debugged, it don't throw error in my ExtendedXhtmlStringEditorDescriptor class but it throw error in EPiServer.Cms.TinyMce.XhtmlStringEditorDescriptor

I also init default body class. I'm not sure that you will have same problem if you add more step to init body_class. like below 

[ModuleDependency(typeof(TinyMceInitialization))]
    public class CustomizedTinyMceInitialization : IConfigurableModule
    {
        public void Initialize(InitializationEngine context)
        {
        }

        public void Uninitialize(InitializationEngine context)
        {
        }

        public void ConfigureContainer(ServiceConfigurationContext context)
        {

            var startPage = ContentReference.StartPage;
            context.Services.Configure<TinyMceConfiguration>(config =>
            {
                config.Default().EnableImageTools()
                   .AddEpiserverSupport()
                   .AddPlugin("epi-link epi-image-editor epi-dnd-processor epi-personalized-content print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists textcolor wordcount imagetools contextmenu colorpicker textpattern help")
                   .Toolbar("formatselect forecolor backcolor styleselect | epi-personalized-content epi-link anchor numlist bullist indent outdent bold italic underline alignleft aligncenter alignright alignjustify | image epi-image-editor media code | epi-dnd-processor | removeformat | fullscreen")
                   .BodyClass("DefaultTheme")
                   .StyleFormats(
                       new { title = "White color (will be seen as white on website)", selector = "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img", classes = "white-color" },
                       new
                       {
                           title = "Link button 1",
                           block = "a",
                           classes = new [] {"link-button", "orange" }
                       },
                       new
                       {
                           title = "Link button 2",
                           block = "p",
                           classes = "color-button"
                       },
                                   )
                                   .ContentCss("/Static/editor.style.css");
            });
        }
    }
#205168
Jul 01, 2019 13:47
Vote:
 

Ok, taking a slightly different approach, you could drop the need for your custom XhtmlStringEditorDescriptor by setting the body class in a SettingsTransform which you could register in the TinyMceInitialization module you posted above. In the code below, I've modified the code you posted to add a settings transform which looks up the theme from the start page and applies it as the body class each time a tinyMCE editor is loaded.

[ModuleDependency(typeof(TinyMceInitialization))]
public class CustomizedTinyMceInitialization : IConfigurableModule
{
    public void Initialize(InitializationEngine context)
    {
    }

    public void Uninitialize(InitializationEngine context)
    {
    }

    public void ConfigureContainer(ServiceConfigurationContext context)
    {
        context.Services.Configure<TinyMceConfiguration>(config =>
        {
            config.Default().EnableImageTools()
                .AddEpiserverSupport()
                .AddPlugin("epi-link epi-image-editor epi-dnd-processor epi-personalized-content print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists textcolor wordcount imagetools contextmenu colorpicker textpattern help")
                .Toolbar("formatselect forecolor backcolor styleselect | epi-personalized-content epi-link anchor numlist bullist indent outdent bold italic underline alignleft aligncenter alignright alignjustify | image epi-image-editor media code | epi-dnd-processor | removeformat | fullscreen")
                .BodyClass("DefaultTheme")
                .StyleFormats(
                    new { title = "White color (will be seen as white on website)", selector = "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img", classes = "white-color" },
                    new
                    {
                        title = "Link button 1",
                        block = "a",
                        classes = new[] { "link-button", "orange" }
                    },
                    new
                    {
                        title = "Link button 2",
                        block = "p",
                        classes = "color-button"
                    }
                )
                .ContentCss("/Static/editor.style.css")
                .AddSettingsTransform("SetBodyClass", (settings, content, propertyName) =>
                {
                    var contentLoader = context.StructureMap().GetInstance<IContentLoader>();
                    var startPage = contentLoader.Get<StartPage>(SiteDefinition.Current.StartPage);
                    settings.BodyClass(startPage.Theme.ToString());
                });
        });
    }
}

By taking this approach, you can then get rid of your ExtendedXhtmlStringEditorDescriptor and hopefully, in doing so, resolve the original issue.

#205203
Jul 01, 2019 18:51
Linh Le - Jul 02, 2019 8:08
Awesome, you save my day. Thank you very much :D
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* 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.