Lookup Editors How to Create Lookup Editor for code description tables - serenity-is/Serenity GitHub Wiki
Inspired by issue https://github.com/volkanceylan/Serenity/issues/1398 of awesomegithubusername and edson I create this wiki page that describe how create a lookup editor that show data from a code and description field.
In most case tables has a code and a description. In these cases you would like to show at user both data.
First of all create a TypeScript class editor that extend Serenity.LookupEditorBase. The options for this editor are a codeFieldName and descrFieldName. These are needed to specify the fields that contains code value and description value.
    export interface LKCodeDescOptions extends Serenity.LookupEditorOptions {
        codeFieldName: string;
        descrFieldName: string;
    }In the constructor of the editor I set two data attribute int the container object, with the parameters.
namespace MyNameSpace {
  @Serenity.Decorators.registerEditor()
     export class LKCodeDescr extends Serenity.LookupEditorBase<LKCodeDescOptions, any> {
     constructor(container: JQuery, opt?: LKCodeDescOptions)
     {
         super(container, opt);
         container.data("codeName", opt.codeFieldName);
         container.data("descrName", opt.descrFieldName);
     }Then get Select2 options from base class and set the two delegate formatResult formatSelection to our function
    public getSelect2Options() {
        var selec2Options = super.getSelect2Options();
        selec2Options.formatResult = this.myFormatResult;
        selec2Options.formatSelection = this.myFormatSelection;
        return selec2Options;
    }In formatSelection, that return the string shown to the user on select2 after user selection, I get the data parameters from control and use the to accesse the data in item. Then I format the result.
    protected myFormatSelection(item: Serenity.Select2Item): string {
        if (item === undefined)
            return null;
        var code = item.source[this.element.data("codeName")];
        var descr = item.source[this.element.data("descrName")];
        var title = "Code: " + code;
        title += " - " + descr;
        return "<div title='" + title + "'><b>" + code + "</b> - " + descr + "</div>";
    }In formatResult that populates the select2 item per item, I get the data parameters from control and form the single item in select2. At the end I set item.text to make the search possible in both code and description values.
protected myFormatResult(item: Serenity.Select2Item) {
        var code = item.source[this.element.data("codeName")];
        var descr = item.source[this.element.data("descrName")];
        var title = "Code: " + code;
        title += " - " + descr;
        var markup = '<div class="row">' +
                '<div class="col-xs-2" style="white-space: nowrap"><b>' + code + "</b>" + "</div>" +
                '<div class="col-xs-10"><small>' + descr + '</small></div>' +
                '</div>';
        // This for search on code and description
        item.text = code + " " + descr;
        return markup;
    }After that, you have to transform T4 and get the LKCodeDescrAttribute.
To facilitate your use I than extended attribute (that is a partial class) with LKCodeDescrAttribute in a separated file
    public partial class LKCodeDescrAttribute : LookupEditorBaseAttribute
    {
        public LKCodeDescrAttribute(Type lookupType, String codeFieldName, String descriptionFieldName)
            : base(Key)
        {
            if (lookupType == null)
                throw new ArgumentNullException("lookupType");
            var attr = lookupType.GetCustomAttribute<LookupScriptAttribute>(false);
            if (attr == null)
            {
                throw new ArgumentException(String.Format(
                    "'{0}' type doesn't have a [LookupScript] attribute, so it can't " +
                    "be used with a LookupEditor!",
                    lookupType.FullName), "lookupType");
            }
            SetOption("lookupKey", attr.Key);
            base.CodeFieldName = codeFieldName;
            base.DescrFieldName = descriptionFieldName;
        }
    }Then use in Row or Form
    [LKCodeDescr(typeof(Modules.YourLookup), "MyCodeField", "MyDescrField")]Result
Full code of LKCodeDescr.ts :
namespace MyNameSpace {
    @Serenity.Decorators.registerEditor()
    export class LKCodeDescr extends Serenity.LookupEditorBase<LKCodeDescOptions, any> {
        constructor(container: JQuery, opt?: LKCodeDescOptions)
        {
            super(container, opt);
            container.data("codeName", opt.codeName);
            container.data("descrName", opt.descrName);
        }
        public getSelect2Options() {
            var selec2Options = super.getSelect2Options();
            selec2Options.formatResult = this.myFormatResult;
            selec2Options.formatSelection = this.myFormatSelection;
            return selec2Options;
        }
        protected myFormatSelection(item: Serenity.Select2Item): string {
            if (item === undefined)
                return null;
            var code = item.source[this.element.data("codeName")];
            var descr = item.source[this.element.data("descrName")];
            var title = "Code: " + code;
            title += " - " + descr;
            return "<div title='" + title + "'><b>" + code + "</b> - " + descr + "</div>";
        }
        protected myFormatResult(item: Serenity.Select2Item) {
            var code = item.source[this.element.data("codeName")];
            var descr = item.source[this.element.data("descrName")];
            var title = "Code: " + code;
            title += " - " + descr;
            var markup = '<div class="row">' +
                '<div class="col-xs-2" style="white-space: nowrap"><b>' + code + "</b>" + "</div>" +
                '<div class="col-xs-10"><small>' + descr + '</small></div>' +
                '</div>';
            // This for search on code and description
            item.text = code + " " + descr;
            return markup;
        }
    }
    export interface LKCodeDescOptions extends Serenity.LookupEditorOptions {
        codeName: string;
        descrName: string;
    }
}