Ag-Grid - 单元格下拉复选框
Ag-Grid - Cell Dropdown Checkboxes
我需要创建一个包含多行的 ag-grid,但在该行的一个单元格中,它必须是一个下拉菜单,其中包含可以通过复选框选择一个或多个值的选项。
我在牢房里假装的一个例子。
<div class="dropdown" data-control="checkbox-dropdown">
Select
选择所有
Select离子一号
Select离子二
Select离子三
Select离子四
Select离子五
这可能吗?
谢谢
是的,有可能,你可以利用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,
},
我需要创建一个包含多行的 ag-grid,但在该行的一个单元格中,它必须是一个下拉菜单,其中包含可以通过复选框选择一个或多个值的选项。
我在牢房里假装的一个例子。
<div class="dropdown" data-control="checkbox-dropdown">
Select
选择所有 Select离子一号 Select离子二 Select离子三 Select离子四 Select离子五这可能吗?
谢谢
是的,有可能,你可以利用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,
},