Skip to content

CheckBox Group Editor

Sevigor edited this page Aug 19, 2021 · 2 revisions

See original post: https://github.com/volkanceylan/Serenity/issues/4628

End result:

This is my code:

Create CheckboxButtonEditor.ts in Common/Helper

namespace Serenity {

    function Editor(name: string, intf?: any[]) {
        return Decorators.registerEditor('Serenity.' + name + 'Editor', intf)
    }
    import Element = Decorators.element

    export interface CheckboxButtonEditorOptions {
        enumKey?: string;
        enumType?: any;
        lookupKey?: string;
    }

    @Serenity.Decorators.editor()
    @Editor('CheckboxButton', [[IStringValue], [IReadOnly]])
    @Element('<div/>')
    export class CheckboxButtonEditor extends Widget<CheckboxButtonEditorOptions>
        implements IReadOnly {
        constructor(input: JQuery, opt: CheckboxButtonEditorOptions) {
            super(input, opt);

            if (Q.isEmptyOrNull(this.options.enumKey) &&
                this.options.enumType == null &&
                Q.isEmptyOrNull(this.options.lookupKey)) {
                return;
            }

            if (!Q.isEmptyOrNull(this.options.lookupKey)) {
                var lookup = Q.getLookup(this.options.lookupKey);
                for (var item of lookup.items) {
                    var textValue = item[lookup.textField];
                    var text = (textValue == null ? '' : textValue.toString());
                    var idValue = item[lookup.idField];
                    var id = (idValue == null ? '' : idValue.toString());
                    this.addChecbox(id, text);
                }
            }
            else {
                var enumType = this.options.enumType || Serenity.EnumTypeRegistry.get(this.options.enumKey);
                var enumKey = this.options.enumKey;
                if (enumKey == null && enumType != null) {
                    var enumKeyAttr = (ss as any).getAttributes(enumType, Serenity.EnumKeyAttribute, false);
                    if (enumKeyAttr.length > 0) {
                        enumKey = enumKeyAttr[0].value;
                    }
                }

                var values = (ss as any).Enum.getValues(enumType);
                for (var x of values) {
                    var name = (ss as any).Enum.toString(enumType, x);
                    this.addChecbox(x.toString(), Q.coalesce(Q.tryGetText(
                        'Enums.' + enumKey + '.' + name), name));
                }
            }
        }

        protected addChecbox(value: string, text: string) {
            var label = $('<label/>').text(text);
            $('<input type="checkbox"/>').attr('name', this.uniqueName)
                .attr('id', this.uniqueName + '_' + value)
                .attr('value', value).prependTo(label);
            label.appendTo(this.element);
        }

        get_value(): string {
            let val: number[] = new Array();
            this.element.find('input:checked').each((i, e) => {
                val.push(Q.toId($(e).val()));
            });
            return val.join(',');
        }

        get value(): string {
            return this.get_value();
        }

        set_value(value: string): void {
            if (value !== this.get_value()) {
                let values: number[] = [];
                if (!Q.isEmptyOrNull(value))
                    values = value.split(',').map(p => Number(p));
                var inputs = this.element.find('input');
                inputs.each((i, e) => {
                    (e as HTMLInputElement).checked = false;
                });
                
                if (Q.isArray(values)) {
                    values.forEach((v, i) => {
                        let checks = inputs.filter('[value=' + v + ']');
                        if (checks.length > 0) {
                            (checks[0] as HTMLInputElement).checked = true;
                        }
                    })
                } else {
                    let checks = inputs.filter('[value=' + values + ']');
                    if (checks.length > 0) {
                        (checks[0] as HTMLInputElement).checked = true;
                    } 
                }
            }
        }

        set value(v: string) {
            this.set_value(v);
        }

        get_readOnly(): boolean {
            return this.element.attr('disabled') != null;
        }

        set_readOnly(value: boolean): void {
            if (this.get_readOnly() !== value) {
                if (value) {
                    this.element.attr('disabled', 'disabled')
                        .find('input').attr('disabled', 'disabled');
                }
                else {
                    this.element.removeAttr('disabled')
                        .find('input').removeAttr('disabled');
                }
            }
        }
    }
}

In xyzForm.cs or xyzRow.cs with Enum:

        [CheckboxButtonEditor(EnumKey = "PattisonSand.TblInvoices.Status") ]
        public String TestCheckBox { get; set; }

or with Lookup

        [CheckboxButtonEditor(LookupKey = "Default.TblRailcarTypeLookup") ]
        public String TestCheckBox { get; set; }

Use to filter on grid: In xyzRow.cs or xyzColumn.cs

        [CheckboxButtonEditor, QuickFilter]
        public String TestCheckBox  { get; set; }

In zxyGrid.ts

 protected getQuickFilters(): Serenity.QuickFilter<Serenity.Widget<any>, any>[] {

            // get quick filter list from base class, e.g. columns
            let filters = super.getQuickFilters();

            let statusfilter = Q.first(filters, x => x.field == fld.TestCheckBox  );
            statusfilter.element = e => {
                this.statusFilter = e;
                this.statusFilter.parent().find('span.quick-filter-label').remove();
            };
            statusfilter.handler = h => {
                // if filter is active, e.g. editor has some value
                if (h.active) {
                        h.request.Criteria = Serenity.Criteria.and(h.request.Criteria, [[fld.Status], '=', h.value]);
                }
            };

            return filters;
        }

Set ReadOnly in zxyDialog.ts

this.form.TestCheckBox.set_readOnly(true);

If you've upgraded to .net 5, CheckboxButtonEditor.ts will throw errors around the old "ss" namespace.

Inside the final else statement inside the constructor replace with the following

else {
     var enumType = this.options.enumType || EnumTypeRegistry.get(this.options.enumKey);
     var enumKey = this.options.enumKey;

     if (enumKey == null && enumType != null) {

         var enumKeyAttr = Q.getAttributes(enumType, EnumKeyAttribute, false);
         if (enumKeyAttr.length > 0) {
             enumKey = enumKeyAttr[0].value;
         }
     }
     var values = Q.Enum.getValues(enumType);
     for (var x of values) {
         var name = Q.Enum.toString(enumType, x);
         this.addChecbox(x.toString(),
              Q.coalesce(Q.tryGetText('Enums.' + enumKey + '.' + name), name));
     }
}

Regards

Clone this wiki locally