Nibble

Archive for the 'datatype' Category


MASTER OF DATATYPES, the video 4

The video wasn’t available when I posted the slidedeck and sourcecode so now you can also watch the “Master of Datatypes” session. See how  easy it is to create your own custom umbraco datatypes (I’m creating 3 new datatypes in 30 minutes in the video).

Make sure to check out the buug.be site since you can watch all the other sessions from the Umbraco Be Festival to!

http://www.buug.be/en/events/umbraco-festival

Creating custom umbraco datatypes revisited 3

Umbraco v4.0.1 introduces the abstract dataeditor class to make it easier to build custom datatypes.

So I tried to port the char limit datatype that I showed in the ‘creating custom umbraco datatypes’.

This is how it looks:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace charLimitAbstractDataEditor
{
    public class DataType: umbraco.cms.businesslogic.datatype.AbstractDataEditor
    {
 
        private charLimitPrevalueEditor _prevalueeditor;
      
        private CharlimitControl m_control = new CharlimitControl();
 
 
        public override Guid Id
        {
            get
            {
                return new Guid(“a5dd5b89-74f5-4ed3-b855-f98ae07ea1ec”);
            }
        }
        public override string DataTypeName
        {
            get
            {
                return “CharLimit (AbstractDataEditor)”;
            }
        }
 
        public override umbraco.interfaces.IDataPrevalue PrevalueEditor
        {
            get
            {
                if (_prevalueeditor == null)
                    _prevalueeditor = new charLimitPrevalueEditor(this);
                return _prevalueeditor;
            }
        }
        public DataType()
        {
 
            base.RenderControl = m_control;
            m_control.Init += new EventHandler(m_control_Init);
            base.DataEditorControl.OnSave += new umbraco.cms.businesslogic.datatype.AbstractDataEditorControl.SaveEventHandler(DataEditorControl_OnSave);
        }
 
        void m_control_Init(object sender, EventArgs e)
        {
            m_control.Text = base.Data.Value != null ? base.Data.Value.ToString() : “”;
            m_control.Limit = Convert.ToInt32(((charLimitPrevalueEditor)PrevalueEditor).Configuration);
            
        }
 
        void DataEditorControl_OnSave(EventArgs e)
        {
            base.Data.Value = m_control.Text;
        }
       
    }
}

 

So you just need to inherit from umbraco.cms.businesslogic.datatype.AbstractDataEditor and override the Guid and the DataTypeName property.

If you also need a custom PrevalueEditor (datatype settings) you will also need to override the PrevalueEditor property.

Next step is to set the RenderControl in the constructor, the rendercontrol is just a custom control.

In this case it’s the CharLimitControl

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI;
 
namespace charLimitAbstractDataEditor
{
    public class CharlimitControl: System.Web.UI.WebControls.Panel
    {
        private TextBox txtCharLimit;
        private Label lblLimitInfo;
 
        protected override void OnInit(EventArgs e)
        {
 
            base.OnInit(e);
 
            txtCharLimit.Text = this.Text;
            txtCharLimit.TextMode = TextBoxMode.MultiLine;
            txtCharLimit.Rows = 10;
            txtCharLimit.Columns = 40;
            txtCharLimit.CssClass = “umbEditorTextFieldMultiple”;
            txtCharLimit.Attributes.Add(“onkeyup”, string.Format(“limitChars(this, {1}, ‘{0}’)”, “charlimitstatus” + this.ClientID, Limit.ToString()));
 
            lblLimitInfo = new Label();
 
            lblLimitInfo.Attributes.Add(“id”, “charlimitstatus” + this.ClientID);
 
 
            this.Controls.Add(txtCharLimit);
 
            this.Controls.Add(new LiteralControl(“<br/>”));
            this.Controls.Add(lblLimitInfo);
 
 
            string functionlimit = “function limitChars(textarea, limit, infodiv)”;
            functionlimit += “{”;
            functionlimit += “var text = textarea.value;”;
            functionlimit += “var textlength = text.length;”;
            functionlimit += “var info = document.getElementById(infodiv);”;
 
            functionlimit += “if(textlength > limit)”;
            functionlimit += “{”;
            functionlimit += “info.innerHTML = ‘You cannot write more then ‘+limit+’ characters!’;”;
            functionlimit += “textarea.value = text.substr(0,limit);”;
            functionlimit += “return false;”;
            functionlimit += “}”;
            functionlimit += “else”;
            functionlimit += “{”;
            functionlimit += “info.innerHTML = ‘You have ‘+ (limit - textlength) +’ characters left.’;”;
            functionlimit += “return true;”;
            functionlimit += “}”;
            functionlimit += “}”;
 
            ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), “limitChars”, functionlimit, true);
        }
 
        private int _limit;
        public int Limit
        {
            get
            {
                return _limit;
            }
            set
            {
                _limit = value;
            }
 
 
 
        }
 
        public string _text;
        public string Text
        {
            get
            {
                return txtCharLimit.Text;
            }
            set
            {
                if (txtCharLimit == null)
                    txtCharLimit = new TextBox();
                txtCharLimit.Text = value;
            }
        }
    }
}

 

On init I just pass the stored value and the prevalue editor configuration to the custom control.

        void m_control_Init(object sender, EventArgs e)
        {
            m_control.Text = base.Data.Value != null ? base.Data.Value.ToString() : “”;
            m_control.Limit = Convert.ToInt32(((charLimitPrevalueEditor)PrevalueEditor).Configuration);
            
        }

 

Last step is to subscribe to the base.DataEditorControl.OnSave event and set the base.Data.Value (in this case to the custom control Text property)

        void DataEditorControl_OnSave(EventArgs e)
        {
            base.Data.Value = m_control.Text;
        }

 

Download sourcecode

Creating custom umbraco datatypes 23

A couple of months ago I did a blog post about Creating custom datatypes using the umbraco usercontrol wrapper , I mentioned in that post that there was also an other way of creating a custom datatype. So in this post I’ll try to show you how to create a datatype using the 3 classes way. One of the main differences between this approach and the wrapper is that you’ll be able to have settings for your datatype.

I made a very basic datatype, the char limit datatype I’ll just show how I created that one.

First step would be to create a new project in visual studio (I tend to start a new class library, but web application should also be fine) and reference the necessary umbraco assemblies (so make sure you have those, just download v4).

Here is how the solution explorer looks when the char limit solution is opened.

customdatatype

The umbraco assemblies that needs to be referenced are businesslogic, cms, interfaces, umbraco.Datalayer and umbraco.editorControls (you can find these in the bin directory of umbraco).

As you can notice in the solution explorer the projects contains 3 files.

  • charLimitDataEditor.cs
  • charLimitDataType.cs
  • charLimitPrevalueEditor.cs

These are 3 classes (that’s wy I call it the 3 classes way) implementing the necessary umbraco interfaces.

I’ll start by showing the contents of charLimitDataType.cs

using System;
using System.Collections.Generic;
using System.Text;
 
namespace Nibble.Umb.Datatypes.CharLimit
{
    public class charLimitDataType : umbraco.cms.businesslogic.datatype.BaseDataType, umbraco.interfaces.IDataType
    {
        private umbraco.interfaces.IDataEditor _Editor;
        private umbraco.interfaces.IData _baseData;
        private charLimitPrevalueEditor _prevalueeditor;
 
        public override umbraco.interfaces.IDataEditor DataEditor
        {
            get
            {
                if (_Editor == null)
                    _Editor = new charLimitDataEditor(Data, ((charLimitPrevalueEditor)PrevalueEditor).Configuration);
                return _Editor;
            }
        }
 
        public override umbraco.interfaces.IData Data
        {
            get
            {
                if (_baseData == null)
                    _baseData = new umbraco.cms.businesslogic.datatype.DefaultData(this);
                return _baseData;
            }
        }
        public override Guid Id
        {
            get { return new Guid(“71518B4E-B1A5-11DD-A22C-8AAA56D89593″); }
        }
 
        public override string DataTypeName
        {
            get { return “Char Limit Textarea”; }
        }
 
        public override umbraco.interfaces.IDataPrevalue PrevalueEditor
        {
            get
            {
                if (_prevalueeditor == null)
                    _prevalueeditor = new charLimitPrevalueEditor(this);
                return _prevalueeditor;
            }
        }
    }
}

 

This is basicly where you give the datatype it’s name and unique id. The name will show up in the rendercontrol dropdown of the edit datatype page.

customdatatype2

Each datatype needs to have a guid, when creating a new datatype make sure you change this to a unique one.

Next is the charLimitPrevalueEditor.cs file

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using umbraco.DataLayer;
using umbraco.BusinessLogic;
using umbraco.editorControls;
 
namespace Nibble.Umb.Datatypes.CharLimit
{
    public class charLimitPrevalueEditor : System.Web.UI.WebControls.PlaceHolder, umbraco.interfaces.IDataPrevalue
    {
        #region IDataPrevalue Members
 
        // referenced datatype
        private umbraco.cms.businesslogic.datatype.BaseDataType _datatype;
 
      
        private TextBox _txtLimit;
 
        public charLimitPrevalueEditor(umbraco.cms.businesslogic.datatype.BaseDataType DataType)
        {
 
            _datatype = DataType;
            setupChildControls();
 
        }
 
        private void setupChildControls()
        {
            
            _txtLimit = new TextBox();
            _txtLimit.ID = “txtLimit”;
            _txtLimit.CssClass = “umbEditorTextField”;
 
 
            Controls.Add(_txtLimit);
 
        }
 
 
 
        public Control Editor
        {
            get
            {
                return this;
            }
        }
 
 
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (!Page.IsPostBack)
            {
                
                if (Configuration.Length > 0)
                {
 
                    _txtLimit.Text = Configuration;
 
                }
                else
                {
                    _txtLimit.Text = “100″;
                }
 
 
            }
 
 
        }
 
        public void Save()
        {
            _datatype.DBType = (umbraco.cms.businesslogic.datatype.DBTypes)Enum.Parse(typeof(umbraco.cms.businesslogic.datatype.DBTypes), DBTypes.Ntext.ToString(), true);
 
 
            string data = _txtLimit.Text;
 
            SqlHelper.ExecuteNonQuery(“delete from cmsDataTypePreValues where datatypenodeid = @dtdefid”, 
                    SqlHelper.CreateParameter(“@dtdefid”, _datatype.DataTypeDefinitionId));
            SqlHelper.ExecuteNonQuery(“insert into cmsDataTypePreValues (datatypenodeid,[value],sortorder,alias) values (@dtdefid,@value,0,”)”, 
                    SqlHelper.CreateParameter(“@dtdefid”, _datatype.DataTypeDefinitionId), SqlHelper.CreateParameter(“@value”, data));
 
        }
 
        protected override void Render(HtmlTextWriter writer)
        {
            writer.WriteLine(“<table>”);
            writer.Write(“<tr><th>Character Limit:</th><td>”);
            _txtLimit.RenderControl(writer);
            writer.Write(“</td></tr>”);
            writer.Write(“</table>”);
        }
 
        public string Configuration
        {
            get
            {
                object conf =
                   SqlHelper.ExecuteScalar<object>(“select value from cmsDataTypePreValues where datatypenodeid = @datatypenodeid”,
                                           SqlHelper.CreateParameter(“@datatypenodeid”, _datatype.DataTypeDefinitionId));
 
                if (conf != null)
                    return conf.ToString();
                else
                    return “”;
 
            }
        }
 
        #endregion
 
        public static ISqlHelper SqlHelper
        {
            get
            {
                return Application.SqlHelper;
            }
        }
    }
}

This class is used to setup the datatype settings (something you can’t do when using the wrapper method). In this case it shows a textbox wich will be used to set the character limit. On save it will store this value (using the datalayer) in the database.

customdatatypes3

Last one is charLimitDataEditor.cs

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using umbraco.interfaces;
 
namespace Nibble.Umb.Datatypes.CharLimit
{
    public class charLimitDataEditor : System.Web.UI.UpdatePanel, umbraco.interfaces.IDataEditor
    {
 
        private umbraco.interfaces.IData _data;
           
        private string CharLimit;
 
        private TextBox txtCharLimit;
        private Label lblLimitInfo;
 
        public charLimitDataEditor(umbraco.interfaces.IData Data, string Configuration)
        {
            _data = Data;
 
            if (Configuration.Length > 0)
            {
                CharLimit = Configuration;
            }
            else
            {
                CharLimit = “100″;
            }
        }
 
        public virtual bool TreatAsRichTextEditor
        {
            get { return false; }
        }
 
        public bool ShowLabel
        {
            get { return true; }
        }
 
        public Control Editor { get { return this; } }
 
        public void Save()
        {
 
            this._data.Value = txtCharLimit.Text;
            
        }
 
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
 
 
            txtCharLimit = new TextBox();
 
            txtCharLimit.Text = _data.Value.ToString();
            txtCharLimit.TextMode = TextBoxMode.MultiLine;
            txtCharLimit.Rows = 10;
            txtCharLimit.Columns = 40;
            txtCharLimit.CssClass = “umbEditorTextFieldMultiple”;
            txtCharLimit.Attributes.Add(“onkeyup”, string.Format(“limitChars(this, {1}, ‘{0}’)”, “charlimitstatus” + base.ClientID, CharLimit));
 
           
 
 
            lblLimitInfo = new Label();
            
            lblLimitInfo.Attributes.Add(“id”, “charlimitstatus” + base.ClientID);
            
 
            base.ContentTemplateContainer.Controls.Add(txtCharLimit);
 
            base.ContentTemplateContainer.Controls.Add(new LiteralControl(“<br/>”));
            base.ContentTemplateContainer.Controls.Add(lblLimitInfo);
 
 
            string functionlimit = “function limitChars(textarea, limit, infodiv)”;
            functionlimit += “{”;
            functionlimit += “var text = textarea.value;”;
            functionlimit += “var textlength = text.length;”;
            functionlimit += “var info = document.getElementById(infodiv);”;
 
            functionlimit += “if(textlength > limit)”;
            functionlimit += “{”;
            functionlimit += “info.innerHTML = ‘You cannot write more then ‘+limit+’ characters!’;”;
            functionlimit += “textarea.value = text.substr(0,limit);”;
            functionlimit += “return false;”;
            functionlimit += “}”;
            functionlimit += “else”;
            functionlimit += “{”;
            functionlimit += “info.innerHTML = ‘You have ‘+ (limit - textlength) +’ characters left.’;”;
            functionlimit += “return true;”;
            functionlimit += “}”;
            functionlimit += “}”;
 
            ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), “limitChars”, functionlimit, true);
 
        }
      
    }
}

This one is used for the actual datatype dataeditor, so the control you will get in the content section of umbraco.

customdatatypes4

This class inherits from the updatepanel class and implements the umbraco.interfaces.IDataEditor. So on init you need to add the controls, in this case a textbox and a literal (for the info text on character limit) and fetch the saved data. And in the save method you can set what value needs to be saved.

Feel free to experiment with the sourcecode.

Download sourcecode

New Package - Char Limit 18

This is a very basic package,  it’s just a new datatype, a textarea with a limit on the characters.

The character limit can be set on the edit datatype page (default this is set to 100).

charlimit2

In the content section it looks like this (these are 2 char limit properties):

charlimit1

So you get feedback on the amount of characters left when you are typing. If you exceed the limit the content gets trimmed.

Since umbraco v4 is just around the corner, this package is one for v4 (using the datalayer and it also works in liveediting mode).

The reason I created this datatype was to have a simple example to show how to create a datatype, so you can expect a blog post explaining the creation of a datatype soon…

Char Limit Package: download

A look at the related links datatype in umbraco v4 18

A couple of weeks ago I released the related links package for umbraco v3. Recently the related links datatype has also been added as a default datatype in umbraco v4 (a more polished version).

I recorded a screencast wich will show you how to use the datatype in v4.

relatedlinksdatatype