Ag-Grid - 单元格下拉复选框

Ag-Grid - Cell Dropdown Checkboxes

我需要创建一个包含多行的 ag-grid,但在该行的一个单元格中,它必须是一个下拉菜单,其中包含可以通过复选框选择一个或多个值的选项。

我在牢房里假装的一个例子。

<div class="dropdown" data-control="checkbox-dropdown">

Select

选择所有 Select离子一号 Select离子二 Select离子三 Select离子四 Select离子五

Codepen

这可能吗?

谢谢

是的,有可能,你可以利用cellRenderer。一个例子:

{
  headerName: 'Dropdown',
  field: 'dropdown',
  cellRenderer: params => {
    
    let div = document.createElement('div');
    // you can create your dropdown here
    return div;
  }
}

我不得不使用自定义单元格编辑器,这是代码(纯 JS 和一些 jQuery 帮助使 DOM 的东西更容易)。

Demo(心情栏): https://plnkr.co/plunk/QBf8MdYWuUd0U6dK

CSS:

.checkbox-dropdown-input {
    position: relative;
    margin: 0 auto;
    user-select: none;
}

.checkbox-dropdown {
    //width: 200px;
    border: 1px solid #aaa;
    padding: 10px;
    position: relative;
    margin: 0 auto;

    user-select: none;
}

/* Display CSS arrow to the right of the dropdown text */
.checkbox-dropdown:after {
    content:'';
    height: 0;
    position: absolute;
    width: 0;
    border: 6px solid transparent;
    border-top-color: #000;
    top: 50%;
    right: 10px;
    margin-top: -3px;
}

/* Reverse the CSS arrow when the dropdown is active */
.checkbox-dropdown.is-active:after {
    border-bottom-color: #000;
    border-top-color: #fff;
    margin-top: -9px;
}

.checkbox-dropdown-list {
    list-style: none;
    margin: 0;
    padding: 0;
    position: absolute;
    top: 100%; /* align the dropdown right below the dropdown text */
    border: inherit;
    border-top: none;
    left: -1px; /* align the dropdown to the left */
    right: -1px; /* align the dropdown to the right */
    opacity: 0; /* hide the dropdown */

    transition: opacity 0.4s ease-in-out;
    height: 100px;
    overflow: scroll;
    overflow-x: hidden;
    pointer-events: none; /* avoid mouse click events inside the dropdown */
}
.is-active .checkbox-dropdown-list {
    opacity: 1; /* display the dropdown */
    pointer-events: auto; /* make sure that the user still can select checkboxes */
}

.checkbox-dropdown-list li label {
    display: block;
    border-bottom: 1px solid silver;
    padding: 10px;

    transition: all 0.2s ease-out;

    background-color: white;
    color: black;
}

.checkbox-dropdown-list li label:hover {
    background-color: #555;
    color: white;
}

和 JS:

class CheckboxDropDownRenderer{
    init(params){
        this.params = params;
        this.eGui = document.createElement('div');
        this.eGui.className = "checkbox-dropdown-input";
        this.eGui.tabIndex = '0'; // to allow the div to capture keypresses
        this.inp = document.createElement('input');
        let colWidth = params.column.actualWidth - (2*parseInt($(".ag-cell").css("padding-left")));
        this.eGui.style.width = colWidth + "px";
        this.inp.style.width = colWidth + "px";
        this.inp.value = params.value;
        this.eGui.appendChild(this.inp);
    }
    getGui() {
        return this.eGui;
    }
}
class CheckboxDropDownEditor {
  // idea from: https://codepen.io/thecel/pen/EVeGpB
  // alternate method, didn't try, but leaving here just in case https://codepen.io/RobotsPlay/pres/pyNLdL

    init(params){
        this.do_cancel = true;
        this.params = params;
        this.eGui = document.createElement('div');
        this.eGui.tabIndex = '0'; // to allow the div to capture keypresses
        this.eGui.className = "is-active checkbox-dropdown";//
        this.parents_left_padding = parseInt($(".ag-cell").css("padding-left"));
        let colWidth = params.column.actualWidth - (1.5*this.parents_left_padding);
        this.eGui.style.width = colWidth + "px";
        this.ul = document.createElement('ul');
        this.ul.className = "checkbox-dropdown-list";
        //this.container.style = 'border-radius: 15px; border: 1px solid grey;background: #e6e6e6;padding: 15px; text-align:center;display:inline-block;outline:none';

        let selections_available = params.selection_list; // comes from columnDefs property, i.e. cellRendererParams: {selection_list: status_available}}
        let currentSelected = split_children(params.value);
        for (var i in selections_available) {
            let key = selections_available[i];
            let li = document.createElement('li');
            let label = document.createElement('label');
            let inp = document.createElement('input');
            inp.type="checkbox"; inp.value=key;
            label.innerHTML = key;

            if (currentSelected.includes(key)) {
                inp.checked = true;
                delete_from_array(key, currentSelected);
            }

            label.appendChild(inp);
            li.appendChild(label);
            this.ul.appendChild(li);
        }
        console.log('popup owner editor has these values remaining to add to the list: '+ currentSelected);
        // handle values that were manually entered into the text box
        for (var i in currentSelected) {
            let key = currentSelected[i];
            let li = document.createElement('li');
            let label = document.createElement('label');
            let inp = document.createElement('input');
            inp.type="checkbox"; inp.value=key;
            label.innerHTML = key;
            inp.checked = true;
            label.appendChild(inp);
            li.appendChild(label);
            this.ul.appendChild(li);
        }
        this.eGui.appendChild(this.ul);
        this.value = params.value;
        let that = this;
        $(this.eGui).click(function () {
            $(this).toggleClass("is-active");
            that.params.stopEditing();
        });
        this.ul.addEventListener('keydown', (event) => {
            const key = event.key;
            console.log('owner popup saw keypress: '+key);
        //    if (
        //      key === 'ArrowLeft' || // left
        //      key === 'ArrowRight'
        //    ) {
        //      // right
        //      this.toggleMood();
        //    }
//              event.stopPropagation();
        });
        $(this.ul).click(function(e) {
            that.do_cancel=false;
            e.stopPropagation();
            let my_val = e.target.value;
            if (e.target.checked){
                if (that.value==""){
                    that.value = my_val;
                } else {
                    that.value += "," + my_val;
                }
            } else {
                let current_vals = split_children(that.value);
                delete_from_array(my_val, current_vals);
                that.value = String(current_vals);
            }
        });
    }

    isPopup() {
        return true;
    }
    getPopupPosition(){
      return ("under");
    }
    getGui() {
        return this.eGui;
    }
    getValue() {
        return this.value;
    }
    isCancelAfterEnd() {
      if (this.do_cancel){
        let textInputElement = this.params.eGridCell.children[0].children[0];
        let textinput_val = textInputElement.value;
        this.value = textinput_val;
      }
      return false;
    }
}

function split_children(children){
    let myarray = children.split(',');
    return delete_from_array("", myarray);
}
function delete_from_array(item_to_delete, myarray){
    let index = $.inArray(item_to_delete, myarray);
    if (index>=0) myarray.splice(index, 1);
    return myarray;
}

然后在你的 defs 列中(前提是你有 drop-down 到 pre-populate 的字符串列表,users_list 在这里):

{ field: "owner", headerName:"Owner", editable: true,
    cellRenderer: CheckboxDropDownRenderer,
    singleClickEdit: true,
    cellEditorParams: {selection_list: users_list},
    cellEditor: CheckboxDropDownEditor,
},