Showing posts with label AJAX HTML Editor. Show all posts
Showing posts with label AJAX HTML Editor. Show all posts

Tuesday, 2 June 2009

HTML Editor FieldTemplate for Dynamic Data Using AJAX Control Toolkit Editor

I decided to create an HTML Edit FieldTemplate after the AJAX Control Toolkit HTML Editor was released and a post (Edit.aspx page hanging on text entry) on the ASP.Net Dynamic Data Forum was posted.

For this we will need two FieldTemplates:

  1. Html.ascx
  2. Html_Edit.ascx

The first of the two Html.ascx will display the HTML rendered correctly and the second will use the AJAX Control Toolkit HTML Editor.

The Normal FieldTemplate

<%@ Control 
    Language="C#" 
    Inherits="DD_HTMLEditor.Html_Field" 
    Codebehind="Html.ascx.cs" %>

<asp:Literal 
    runat="server" 
    ID="Literal1" 
    Text="<%# FieldValueEditString %>" />

Listing 1 – Html.ascx

using System;
using System.Web.UI;

namespace DD_HTMLEditor
{
    public partial class Html_Field : System.Web.DynamicData.FieldTemplateUserControl
    {
        public override Control DataControl
        {
            get
            {
                return Literal1;
            }
        }
    }
}

Listing 2 – Html.ascx.cs

As you can see this is a direct copy of the Text.ascx FieldTemplate the only change is to Literal1 in the ascx file instead of FieldValueString we are using FieldValueEditString.

Description Field Showing HTML

Figure 1 – Description Field Showing HTML

The Edit FieldTemplate

<%@ Control 
    Language="C#" 
    Inherits="DD_HTMLEditor.Html_EditField" 
    Codebehind="Html_Edit.ascx.cs" %>
    
<%@ Register 
    Assembly="AjaxControlToolkit" 
    Namespace="AjaxControlToolkit.HTMLEditor"
    TagPrefix="cc1" %>

<cc1:Editor 
    ID="Editor1" 
    Content='<%# FieldValueEditString %>'
    runat="server" />
    
<asp:RequiredFieldValidator 
    runat="server" 
    ID="RequiredFieldValidator1" 
    CssClass="droplist" 
    ControlToValidate="Editor1" 
    Display="Dynamic" 
    Enabled="false" />
    
<asp:RegularExpressionValidator 
    runat="server" 
    ID="RegularExpressionValidator1" 
    CssClass="droplist" 
    ControlToValidate="Editor1" 
    Display="Dynamic" 
    Enabled="false" />
    
<asp:DynamicValidator 
    runat="server" 
    ID="DynamicValidator1" 
    CssClass="droplist" 
    ControlToValidate="Editor1" 
    Display="Dynamic" />

Listing 3 – Html_Edit.ascx file

using System;
using System.Collections.Specialized;
using System.Web.UI;

namespace DD_HTMLEditor
{
    public partial class Html_EditField : System.Web.DynamicData.FieldTemplateUserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            SetUpValidator(RequiredFieldValidator1);
            RequiredFieldValidator1.Text = "*";
            SetUpValidator(RegularExpressionValidator1);
            RegularExpressionValidator1.Text = "*";
            SetUpValidator(DynamicValidator1);
            DynamicValidator1.Text = "*";
        }

        protected override void ExtractValues(IOrderedDictionary dictionary)
        {
            dictionary[Column.Name] = ConvertEditedValue(Editor1.Content);
        }

        public override Control DataControl
        {
            get
            {
                return Editor1;
            }
        }
    }
}

Listing 4 – Html_Edit.ascx.cs file

Here again it’s just the Text_Edit FieldTemplate with a few minor changes (shown in BOLD ITALIC). First we added the AJAC Control Toolkit HTML Editor control to replace the TextBox control and added a reference to the FieldTemplate.

Note:

You could also add a reference for the AJAX Control Toolkit to the web.config

<pages>
    <controls>
        <add tagPrefix="ajaxToolkit"
            namespace="AjaxControlToolkit"
            assembly="AjaxControlToolkit"/>
    </controls>
</pages>

Description Field in Edit mode

Figure 2 – Description Field in Edit mode

Next Steps

Next we need to add some of the configurability of the HTML Editor via a custom Attribute.
using System;
using System.Linq;
using System.Web.DynamicData;
using AjaxControlToolkit.HTMLEditor;

namespace DD_HTMLEditor
{
    /// <summary>
    /// Attribute to identify which column to use as a 
    /// parent column for the child column to depend upon
    /// </summary>
    [AttributeUsage(AttributeTargets.Property)]
    public class HtmlEditorAttribute : Attribute
    {
        /// <summary>
        /// Default Contructor
        /// </summary>
        public HtmlEditorAttribute()
        {
        }

        /// <summary>
        /// Active editing panel (Design, Html, Preview) on control loaded 
        /// </summary>
        public AjaxControlToolkit.HTMLEditor.ActiveModeType ActiveMode { get; set; }

        /// <summary>
        /// If true, editing panel is focused and cursor is set 
        /// inside it ("Design" or "HTML text") on initial load 
        /// or editing panel change
        /// </summary>
        public Boolean AutoFocus { get; set; }

        /// <summary>
        /// A css class override used to define a custom look 
        /// and feel for the HTMLEditor. See the HTMLEditor 
        /// Theming section for more details
        /// </summary>
        public String CssClass { get; set; }

        /// <summary>
        /// Sets the path of additional CSS file used for 
        /// HTMLEditor's content rendering in "Design" panel. 
        /// If not set, the default CSS file is used which is 
        /// embedded as a WebResource and is a 
        /// part of the Toolkit assembly
        /// </summary>
        public String DesignPanelCssPath { get; set; }

        /// <summary>
        /// Sets the path of CSS file used for HTMLEditor's 
        /// content rendering in "Design" and "Preview" panels. 
        /// If not set, the default CSS file is used which is 
        /// embedded as a WebResource and is a part of the 
        /// Toolkit assembly
        /// </summary>
        public String DocumentCssPath  { get; set; }

        /// <summary>
        /// A css class override used to define a custom look for the 
        /// HTMLEditor's "HTML text" mode panel. See the HTMLEditor 
        /// Theming section for more details
        /// </summary>
        public String HtmlPanelCssClass  { get; set; }

        /// <summary>
        /// If true, Tab key navigation is suppressed inside 
        /// HTMLEditor control 
        /// </summary>
        public Boolean IgnoreTab  { get; set; }

        /// <summary>
        /// If true, HTMLEditor's content is cleaned up on 
        /// initial load. MS Word specific tags are removed 
        /// </summary>
        public Boolean InitialCleanUp  { get; set; }

        /// <summary>
        /// If true, JavaScript code is suppressed 
        /// in HTMLEditor's content 
        /// </summary>
        public Boolean NoScript  { get; set; }

        /// <summary>
        ///  If true, all Unicode characters in 
        ///  HTML content are replaced with &#code;
        /// </summary>
        public Boolean NoUnicode { get; set; }

        /// <summary>
        /// The client-side script that executes after 
        /// active mode (editing panel) changed
        /// </summary>
        public String OnClientActiveModeChanged { get; set; }

        /// <summary>
        /// The client-side script that executes before 
        /// active mode (editing panel) changed
        /// </summary>
        public String OnClientBeforeActiveModeChanged { get; set; }

        /// <summary>
        /// If true, no white spaces inserted on Tab key 
        /// press in Design mode. Default Tab key navigation 
        /// is processing in this case 
        /// </summary>
        public Boolean SuppressTabInDesignMode { get; set; }

        /// <summary>
        /// Sets the height of the body of the HTMLEditor 
        /// </summary>
        public int Height { get; set; }

        /// <summary>
        /// Sets the width of the body of the HTMLEditor 
        /// </summary>
        public int Width { get; set; }
    }

    public static partial class HelperExtansionMethods
    {
        /// <summary>
        /// Get the attribute or a default instance of the attribute
        /// if the Column attribute do not contain the attribute
        /// </summary>
        /// <typeparam name="T">
        /// Attribute type
        /// </typeparam>
        /// <param name="table">
        /// Column to search for the attribute on.
        /// </param>
        /// <returns>
        /// The found attribute or a default 
        /// instance of the attribute of type T
        /// </returns>
        public static T GetAttributeOrDefault<T>(this MetaColumn column) where T : Attribute, new()
        {
            return column.Attributes.OfType<T>().DefaultIfEmpty(new T()).FirstOrDefault();
        }
    }
}

Listing 5 – HtmlEditorAttribute

var htmlAttr = Column.GetAttributeOrDefault<HtmlEditorAttribute>();
if (htmlAttr.ActiveMode != ActiveModeType.Design)
    Editor1.ActiveMode = htmlAttr.ActiveMode;
if (htmlAttr.AutoFocus)
    Editor1.AutoFocus = true;
if (htmlAttr.CssClass != null)
    Editor1.CssClass = htmlAttr.CssClass;
if (htmlAttr.DesignPanelCssPath != null)
    Editor1.DesignPanelCssPath = htmlAttr.DesignPanelCssPath;
if (htmlAttr.DocumentCssPath != null)
    Editor1.DocumentCssPath = htmlAttr.DocumentCssPath;
if (htmlAttr.Height > 0)
    Editor1.Height = htmlAttr.Height;
if (htmlAttr.HtmlPanelCssClass != null)
    Editor1.HtmlPanelCssClass = htmlAttr.HtmlPanelCssClass;
if (htmlAttr.IgnoreTab)
    Editor1.IgnoreTab = true;
if (htmlAttr.InitialCleanUp)
    Editor1.InitialCleanUp = true;
if (htmlAttr.NoScript)
    Editor1.NoScript = true;
if (htmlAttr.NoUnicode)
    Editor1.NoUnicode = true;
if (htmlAttr.OnClientActiveModeChanged != null)
    Editor1.OnClientActiveModeChanged = htmlAttr.OnClientActiveModeChanged;
if (htmlAttr.OnClientBeforeActiveModeChanged != null)
    Editor1.OnClientBeforeActiveModeChanged = htmlAttr.OnClientBeforeActiveModeChanged;
if (htmlAttr.SuppressTabInDesignMode)
    Editor1.SuppressTabInDesignMode = true;
if (htmlAttr.Width > 0)
    Editor1.Width = htmlAttr.Width;

Listing 6 – Attribute setting for Html_Edit.ascx

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using AjaxControlToolkit.HTMLEditor;

namespace DD_HTMLEditor.Models
{
    [MetadataType(typeof(CategoryMD))]
    public partial class Category 
    {
        public partial class CategoryMD
        {
            public object CategoryID {get;set;}
            public object CategoryName {get;set;}

            [UIHint("Html")]
            [HtmlEditor(
                ActiveMode=ActiveModeType.Preview,
                Width=200,
                Height=100
                )]
            public object Description {get;set;}
            public object Picture {get;set;}
            public object Products {get;set;}
        }
    }
}

Listing 7 – Metadata

Above we have the attribute Listing 5 and the code Listing 6 to set the properties of the Html Editor in the Html_Edit.ascx FieldTemplate’s Page_Load event, and finally Listing 7 sample metadata.

Attribute from the Metadata applied

Figure 3 – Attribute from the Metadata applied

Not Rocket Science but a cool Html Editor (Thanks AJAX Toolkit Guys).

download