Slickgrid, column with a drop down select list?
Asked Answered
S

4

23

Hi I was wondering if anyone knows if it's possible to define a column in slickgrid as being a drop down select list. If not does anyone with some experience with slickgrid know how I should go about adding this option?

Thanks

Spindlelegs answered 12/4, 2010 at 15:22 Comment(0)
E
17

I assume you mean a custom cell editor. Here's a sample select-based boolean cell editor from slick.editors.js. You could easily modify it to work with an arbitrary set of possible values.

function YesNoSelectCellEditor($container, columnDef, value, dataContext) {
    var $select;
    var defaultValue = value;
    var scope = this;

    this.init = function() {
        $select = $("<SELECT tabIndex='0' class='editor-yesno'><OPTION value='yes'>Yes</OPTION><OPTION value='no'>No</OPTION></SELECT>");

        if (defaultValue)
            $select.val('yes');
        else
            $select.val('no');

        $select.appendTo($container);

        $select.focus();
    };


    this.destroy = function() {
        $select.remove();
    };


    this.focus = function() {
        $select.focus();
    };

    this.setValue = function(value) {
        $select.val(value);
        defaultValue = value;
    };

    this.getValue = function() {
        return ($select.val() == 'yes');
    };

    this.isValueChanged = function() {
        return ($select.val() != defaultValue);
    };

    this.validate = function() {
        return {
            valid: true,
            msg: null
        };
    };

    this.init();
};
Elseelset answered 12/4, 2010 at 17:53 Comment(1)
Thanks that's the sort of thing I was looking for, guess I'll have to modify it and try and add some parameter to the columns so you can change the columns at on the fly. Similar to what jqGrid has for select lists atm.Spindlelegs
F
38

You probably dont want to make a new select editor for each range of options. Also you may not know that range of all option value beforehand.

In that case you want a flexible range of options in a select type editor. In order to do this you can add an extra option to your column definitions (e.g. called options) like this:

 var columns = [
  {id:"color", name:"Color", field:"color",  options: "Red,Green,Blue,Black,White", editor: SelectCellEditor},
  {id:"lock", name:"Lock", field:"lock",  options: "Locked,Unlocked", editor: SelectCellEditor}
 ]

and access that using args.column.options in the init method of your own SelectEditor object like this:

 SelectCellEditor : function(args) {
        var $select;
        var defaultValue;
        var scope = this;

        this.init = function() {

            if(args.column.options){
              opt_values = args.column.options.split(',');
            }else{
              opt_values ="yes,no".split(',');
            }
            option_str = ""
            for( i in opt_values ){
              v = opt_values[i];
              option_str += "<OPTION value='"+v+"'>"+v+"</OPTION>";
            }
            $select = $("<SELECT tabIndex='0' class='editor-select'>"+ option_str +"</SELECT>");
            $select.appendTo(args.container);
            $select.focus();
        };

        this.destroy = function() {
            $select.remove();
        };

        this.focus = function() {
            $select.focus();
        };

        this.loadValue = function(item) {
            defaultValue = item[args.column.field];
            $select.val(defaultValue);
        };

        this.serializeValue = function() {
            if(args.column.options){
              return $select.val();
            }else{
              return ($select.val() == "yes");
            }
        };

        this.applyValue = function(item,state) {
            item[args.column.field] = state;
        };

        this.isValueChanged = function() {
            return ($select.val() != defaultValue);
        };

        this.validate = function() {
            return {
                valid: true,
                msg: null
            };
        };

        this.init();
    }
Floret answered 20/10, 2010 at 22:37 Comment(5)
Great! Not only did I use your idea for adding a select but the example was also useful to understand better how to pass arguments to the editors.Backbite
@Floret Is it possible to add dynamic options? i.e Suppose i have two dropdowns in grid as editor, based on selection in first, i want the possoble options in second dropdown. Is it possible?Juglandaceous
@VivekVardhan - yes, pass in a function which returns the set of valuesAmorphism
@Floret Is it possible to have dynamic drop down for each row. For example i need to dynamically load drop down based on id. and each row drop down will have different options how do i achieve that ?Monotone
@Floret Can we improve options with Key Value Pair[{"1":"Red","2":"Green"}] for saving data. Need to get value of options on saving json but need to display text on grid.Because in all doropdowns we have a master list which saved somewhereDyanna
E
17

I assume you mean a custom cell editor. Here's a sample select-based boolean cell editor from slick.editors.js. You could easily modify it to work with an arbitrary set of possible values.

function YesNoSelectCellEditor($container, columnDef, value, dataContext) {
    var $select;
    var defaultValue = value;
    var scope = this;

    this.init = function() {
        $select = $("<SELECT tabIndex='0' class='editor-yesno'><OPTION value='yes'>Yes</OPTION><OPTION value='no'>No</OPTION></SELECT>");

        if (defaultValue)
            $select.val('yes');
        else
            $select.val('no');

        $select.appendTo($container);

        $select.focus();
    };


    this.destroy = function() {
        $select.remove();
    };


    this.focus = function() {
        $select.focus();
    };

    this.setValue = function(value) {
        $select.val(value);
        defaultValue = value;
    };

    this.getValue = function() {
        return ($select.val() == 'yes');
    };

    this.isValueChanged = function() {
        return ($select.val() != defaultValue);
    };

    this.validate = function() {
        return {
            valid: true,
            msg: null
        };
    };

    this.init();
};
Elseelset answered 12/4, 2010 at 17:53 Comment(1)
Thanks that's the sort of thing I was looking for, guess I'll have to modify it and try and add some parameter to the columns so you can change the columns at on the fly. Similar to what jqGrid has for select lists atm.Spindlelegs
S
0

If your cell already contains a "select"-tag with multiple options, you can extract this html from the args. The approach differs from the previous answers, but I was personally troubled with these solutions, course my cell already contained a select-tag. I'd like to reuse this cell instead of reconstructing it completely in the this.init. Likewise, I'd like to keep using the same options, as my existing select already have, instead of parsing them to the var column = { ...

The $( args.item[ args.column.field ] ) return the active cells content, which basically just get re-appended to the the container (the cell-object). From if ( document.createEvent ) and down, is just a functionality which automatically opens the dropdown on activation; etc. when you use tabulator to navigate to the cell.

function SelectCellEditor( args ) {
    var $select;
    var defaultValue;
    var scope = this;

    this.init = function () {
        $select = $( args.item[ args.column.field ] );
        $select.appendTo( args.container );
        $select.focus();

        // Force the select to open upon user-activation
        var element = $select[ 0 ];

        if ( document.createEvent ) { // all browsers
            var e = new MouseEvent( "mousedown", {
                bubbles: true,
                cancelable: true,
                view: window
            });

            element.dispatchEvent( e );
        } else if ( element.fireEvent ) { // ie
            element.fireEvent( "onmousedown" );
        }

    };
}

Complet editor for Dropdown html-input -> Dropdown html-output

function SelectCellEditor( args ) {
    var $select = $( args.item[ args.column.field ] );
    var defaultValue;
    var scope = this;

    this.init = function () {
        //$select
        $select.appendTo( args.container );

        // Force the select to open upon user-activation
        var element = $select[ 0 ];

        if ( document.createEvent ) { // all browsers
            var e = new MouseEvent( "mousedown", {
                bubbles: true,
                cancelable: true,
                view: window
            });

            element.dispatchEvent( e );
        } else if ( element.fireEvent ) { // ie
            element.fireEvent( "onmousedown" );
        }

        $select.on("click", function( e ) {
            var selected = $( e.target ).val();

            $select.find( "option" ).removeAttr( "selected" );
            $select.find( "option[value='" + selected + "']" ).attr( "selected", "selected" );
        });

    };

    this.destroy = function () {
        $select.remove();
    };

    this.focus = function () { };

    this.loadValue = function ( item ) { };

    this.serializeValue = function () { };

    // Only runs if isValueChanged returns true
    this.applyValue = function ( item, state ) {
        item[ args.column.field ] = $select[ 0 ].outerHTML;
    };

    this.isValueChanged = function () {
        return true;
    };

    this.validate = function () {
        return {
            valid: true,
            msg: null
        };
    };

    this.init();
}
Sikorsky answered 29/7, 2016 at 19:51 Comment(0)
A
0

Without jq, and inline injected elements, packed in module:

'use strict';
 class SelectCellWidget {
    constructor(args) {
        this._args = args;
        this._$select = undefined;
        this._defaultValue = undefined;
        this._init();
    }
     _init () {
        let selects, container, divend, opt_values;
        const args = this._args;
        if(args.column.options){
            opt_values = args.column.options.split(',');
        }else{
            opt_values = ["yes","no"];
        }
        container = document.createElement("div");
        container.classList.add('select-editable');
        divend = document.createElement('input');
        divend.setAttribute("type", "text");
        divend.setAttribute("name", "format");
        divend.setAttribute("value", "");
        selects = document.createElement("select");//"<select id='Mobility' tabIndex='0' class='editor-select'>"+ option_str +"</select>";
        selects.setAttribute("id", "Mobility");
        selects.setAttribute("tabIndex", 0);
        selects.setAttribute("class", "editor-select");
        for(let i = 0; i < opt_values.length; i++) {
            let v = opt_values[i];
            let option = document.createElement("option");
            option.setAttribute("value", v);
            option.innerText = v;
            selects.appendChild(option);
        }

        container.appendChild(divend);
        container.appendChild(selects);
        this._$select = container;
        args.container[0].appendChild(this._$select);
        this._$select.focus();
        document.getElementById("Mobility").selectedIndex = args.item[args.column.field] ? opt_values.indexOf(args.item[args.column.field]) : 0;
    }
     destroy () {
        this._$select.remove();
    }
     focus () {
        this._$select.focus();
    }
     loadValue (item) {
       this._defaultValue = item[this._args.column.field];
       this._$select.value = this._defaultValue;
    }
     serializeValue () {
        if(this._args.column.options){
            return this._$select.lastElementChild.value;
        }else{
            return (this._$select.lastElementChild.value === "yes");
        }
    }
     applyValue (item,state) {
       item[this._args.column.field] = state;
    }
     isValueChanged () {
       return (this._$select.lastElementChild.value !== this._defaultValue);
    }
     validate () {
       return {
           valid: true,
           msg: null
       };
    }
}
module.exports=SelectCellWidget; 

https://github.com/YaAlfred/SlickgridSelectDropdownWidget

Ahead answered 28/10, 2018 at 13:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.