Slickgrid with only one row editable - javascript

Hello I have an editable grid using slickgrid library and I want to know if there is a way to have only the last row (the one that is added by default on the grid loading) editable and the rest of rows non editable?
The following code I'm using is from the library here : Slickgrid Editable with new row added
<script>
var grid;
var data = [];
var columns = [
{id: "title", name: "Title", field: "title", editor: Slick.Editors.Text},
{id: "desc", name: "Description", field: "description", editor: Slick.Editors.Text},
{id: "duration", name: "Duration", field: "duration", editor: Slick.Editors.Text}
];
var options = {
editable: true,
enableAddRow: true,
enableCellNavigation: true,
asyncEditorLoading: false,
autoEdit: false
};
$(function () {
for (var i = 0; i < 3; i++) {
var d = (data[i] = {});
d["title"] = "Task " + i;
d["description"] = "This is a sample";
d["duration"] = "5 days";
}
grid = new Slick.Grid("#myGrid", data, columns, options);
grid.setSelectionModel(new Slick.CellSelectionModel());
grid.onAddNewRow.subscribe(function (e, args) {
var item = args.item;
grid.invalidateRow(data.length);
data.push(item);
grid.updateRowCount();
grid.render();
});
})
</script>

try this code..to disable all rows except the last row
grid.onBeforeEditCell.subscribe(function(e,args) {
if (args.row === grid.getDataLength()-1) {
return true;
} else {
return false;
}
});

You can subscribe to the "onBeforeEditCell" event and return false based on the logic from args
grid.onBeforeEditCell.subscribe(function (e, args)
{
if (/*logic on args*/)
{
return false;
}
});
Check out this SO post: Disabling specific cell edit in Slick grid

Related

Why does KendoUI grid add a row to the beginning of the grid and not give the User a choice using rowindex?

Im using KendoUi grids everywhere now and need some help ..
When my Kendo grid first loads I want the user to have the rows and an empty row at the BOTTOM not the top to indicate that they can add data . I dont want to use the in built "Add Row Button".
I have the following
Try1
$(document).ready(function ()
{
var grid = $("#grid").data("kendoGrid");
grid.addRow();
$(".k-grid-edit-row").appendTo("#grid tbody");
}
This is supposed to move the row to the bottom of the grid , but it doesnt, it remans on top ?
Try 2
I also tried to do something like
var newRow = { field: "FirstName", Value: "" };
var grid = $("#grid").data("kendoGrid");
grid.dataSource.add(newRow);
This did not work either.
Try 3
But with this try , im not sure if there is a 'load' with the Kendoui Grid, i know there is a keydown , etc
grid.tbody.on('load', function (e)
{
if ($(e.target).closest('tr').is(':last-child'))
{
setTimeout(function ()
{
var totalrows = grid.dataSource.total();
var data = grid.dataSource.data();
var lastItem = data[data.length - 1];
if (typeof lastItem !== 'undefined')
{
if (lastItem.FirstName.trim() != "")
grid.addRow();
}
})
}
}
any help would be great.
The full implementation details is below:
First i add the datasource, this is a simple implementation.
var data = $scope.userdetails;
var dataSource = new kendo.data.DataSource({
transport: {
read: function (e) {
e.success(data);
},
update: function (e) {
e.success();
},
create: function (e) {
var item = e.data;
item.Id = data.length + 1;
e.success(item);
}
},
schema: {
model: {
id: "Id",
fields: {
FirstName: { type: "string" }
}
}
}
});
Then i define the grid
let grid = $("#grid").kendoGrid({
dataSource: dataSource,
scrollable: false,
navigatable: true,
editable: {
createAt: "bottom"
},
dataBound: function (e) {
e.sender.tbody.find(".k-grid-Delete").each(function (idx,
element) {
$(element).removeClass("k-button");
});
},
columns: [
{
field: "FirstName", title: "First Name"
},
{
command: [{ name: "Delete", text: "", click: $scope.delete,
className: "far fa-trash-alt fa-fw" }],
title: " ",
width: "100px",
attributes: { class: "k-grid-column-text-centre" }
}
]
}).data("kendoGrid");
I do the below process to add a blank row only when the user clicks tab on the last cell of the last row, but also want to add a blank when the page first loads with the grid.
grid.tbody.on('keydown', function (e) {
i`enter code here`f (e.keyCode == 9) {
if ($(e.target).closest('tr').is(':last-child')) {
setTimeout(function () {
var totalrows = grid.dataSource.total();
var data = grid.dataSource.data();
var lastItem = data[data.length - 1];
if (typeof lastItem !== 'undefined') {
if (lastItem.FirstName.trim() == "")
return;
}
grid.addRow();
})
}
}
});
This code still adds the row at the top of the grid not the bottom.
$(document).ready(function () {
var newRow = { field: "FirstName", Value: "" };
grid.dataSource.add(newRow);
grid.editRow($("#grid tr").last());
}
There is no other place that i add a row
You try #2 is the right way to go. It probably added a row at the bottom, right? So you just need to programatically edit it:
var newRow = { field: "FirstName", Value: "" };
var grid = $("#grid").data("kendoGrid");
grid.dataSource.add(newRow);
grid.editRow($("#grid tr").last());
Demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Kendo UI Snippet</title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.2.513/styles/kendo.default-v2.min.css"/>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.2.513/js/kendo.all.min.js"></script>
</head>
<body>
<div id="grid"></div>
<script>
let grid = $("#grid").kendoGrid({
toolbar: ["save"],
columns: [
{ field: "name" },
{ field: "age" }
],
dataSource: {
data: [
{ id: 1, name: "Jane Doe", age: 30 },
{ id: 2, name: "John Doe", age: 33 }
],
schema:{
model: {
id: "id",
fields: {
age: { type: "number"}
}
}
}
},
editable: true
}).data('kendoGrid');
grid.dataSource.add({});
grid.editRow($("#grid tr").last());
</script>
</body>
</html>
Dojo
If someone is using the built-in method, just use editable.createAt parameter.

How to show label value in cell dropdown instead of stored value?

I'm using Tabulator.js to create an interactive table. I have a dropdown cell (editor type: select) and have found out how to show different labels when selecting from the list (instructions can be found here, the third way).
When I select something, the stored value is shown, but not the label (which is shown when you click on the list). I'd like the stored value to be the ID from the database, and I don't want the user to see it at all, just the label text.
Here is some example code:
var table = new Tabulator("#example-table", {
data:tabledata, //load row data from array
layout:"fitColumns", //fit columns to width of table
responsiveLayout:"hide", //hide columns that dont fit on the table
tooltips:true, //show tool tips on cells
addRowPos:"top", //when adding a new row, add it to the top of the table
history:true, //allow undo and redo actions on the table
pagination:"local", //paginate the data
paginationSize:7, //allow 7 rows per page of data
movableColumns:true, //allow column order to be changed
resizableRows:true, //allow row order to be changed
initialSort:[ //set the initial sort order of the data
{column:"name", dir:"asc"},
],
columns:[ //define the table columns
{title:"Name", field:"name", editor:"select", editorParams:{
values:{
"steve":"Steve Boberson",
"bob":"Bob Jimmerson",
"jim":"Jim Stevenson",
}
}},
],
});
In similar situation like you, but I used a custom select or native dropdown.
Here are the code to explain all: (uses formatters, keeping the real value...)
Tabulator 4.6.3 DataList and DisplayList Demo for select editor
var userData = [{
"FullName": "",
"LoginName": "none"
}, {
"FullName": "Steve Boberson",
"LoginName": "steve"
}, {
"FullName": "Bob Jimmerson",
"LoginName": "bob"
}, {
"FullName": "Jim Stevenson",
"LoginName": "jim"
}];
var customNativeSelect = function(cell, onRendered, success, cancel) {
var cellRealValue = cell.getElement().dataset.loginName;
cellRealValue = (typeof cellRealValue === "undefined") ? "none" : cellRealValue;
//Create and append select list
var selectList = document.createElement("select");
selectList.style.width = "100%";
selectList.style.boxSizing = "border-box";
onRendered(function() {
selectList.focus();
selectList.style.height = "100%";
});
function onChange() {
if (selectList.selectedOptions[0].value != cellRealValue) {
success(selectList.selectedOptions[0].value);
// Store value to cell dataset; will be done by formatter
/* cell.getElement().dataset.loginName = selectList.selectedOptions[0].value */
alert("Here is what the actual looks like: " + JSON.stringify(cell.getTable().getData()))
} else { // No change
cancel();
}
}
//submit new value on blur or change
selectList.addEventListener("blur", onChange);
//submit new value on enter
selectList.addEventListener("keydown", function(e) {
if (e.keyCode == 13) {
onChange();
}
if (e.keyCode == 27) {
cancel();
}
});
//Create and append the options
for (var i = 0; i < userData.length; i++) {
var option = document.createElement("option");
option.value = userData[i].LoginName;
option.text = userData[i].FullName;
if (userData[i].LoginName === cellRealValue) {
option.selected = "selected";
}
selectList.appendChild(option);
}
return selectList;
};
var filterState = false;
var tabledata = [{
itemId: '3423'
},
{
name: 'steve'
},
{
lastDate: '34/56/0000'
},
{
completed: 'yes'
}
];
var table = new Tabulator("#html-table", {
data: tabledata, //assign data to table
layout: "fitColumns",
tooltips: true,
tooltipsHeader: true,
placeholder: "No Data Available", //display message to user on empty table
height: "300px",
columns: [{
title: "ID",
field: "itemId",
headerFilter: false
}, {
title: "Name",
field: "name",
headerFilter: false,
editor: customNativeSelect,
formatter: function(cell) {
var value = cell.getValue();
for (var i = 0; i < userData.length; i++) {
if (userData[i].LoginName === value) {
// Store value to cell dataset
cell.getElement().dataset.loginName = value;
value = userData[i].FullName;
break;
}
}
return value;
}
}, {
title: "Last Date",
field: "lastDate",
headerFilter: false
}, {
title: "Completed",
field: "completed",
headerFilter: false
}, ]
});
function showHideFilters() {
if (filterState == false) {
table.updateColumnDefinition("itemId", {
headerFilter: true
});
table.updateColumnDefinition("name", {
headerFilter: true
});
table.updateColumnDefinition("lastDate", {
headerFilter: true
});
table.updateColumnDefinition("completed", {
headerFilter: true
});
filterState = true;
} else {
table.updateColumnDefinition("itemId", {
headerFilter: false
});
table.updateColumnDefinition("name", {
headerFilter: false
});
table.updateColumnDefinition("lastDate", {
headerFilter: false
});
table.updateColumnDefinition("completed", {
headerFilter: false
});
filterState = false;
}
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/tabulator/4.6.3/css/tabulator.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tabulator/4.6.3/js/tabulator.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<body>
<button onClick="showHideFilters()">
Show/Hide Filters
</button>
<div id="html-table">
</div>
</body>
</html>
Just swap the values then
const tabledata = [{
name: 'Steve Stevenson'
},
{
name: 'Bob Boberson'
},
{
name: 'Tim Timmersonn'
},
{
name: 'Steve Boberson'
}
];
const table = new Tabulator("#example-table", {
data: tabledata, //load row data from array
layout: "fitColumns", //fit columns to width of table
responsiveLayout: "hide", //hide columns that dont fit on the table
tooltips: true, //show tool tips on cells
addRowPos: "top", //when adding a new row, add it to the top of the table
history: true, //allow undo and redo actions on the table
pagination: "local", //paginate the data
paginationSize: 7, //allow 7 rows per page of data
movableColumns: true, //allow column order to be changed
resizableRows: true, //allow row order to be changed
initialSort: [ //set the initial sort order of the data
{
column: "name",
dir: "asc"
},
],
columns: [ //define the table columns
{
title: "Name",
field: "name",
editor: "select",
editorParams: {
values: {
"Steve Boberson": "steve",
"Bob Jimmerson": "bob",
"Jim Stevenson": "jim"
}
}
},
],
});
<!DOCTYPE html>
<html>
<head>
<link href="https://unpkg.com/tabulator-tables#4.2.7/dist/css/tabulator.min.css" rel="stylesheet">
<script type="text/javascript" src="https://unpkg.com/tabulator-tables#4.2.7/dist/js/tabulator.min.js"></script>
</head>
<body>
<div id="example-table"></div>
</body>
</html>
I encountered the same issue and I found simpler walkaround than creating custom select control. You can create a Map collection or Record which will map select keys on select values and then set up formatter function on a specific select column definition in which you can override the default display value.
composeSelectFormatter(dictionary) {
return (cell) => {
const value = cell.getValue();
if (!value) return value;
return dictionary[value];
}
}
And then in your column definition:
columns: [ //define the table columns
{
title: "Name",
field: "name",
editor: "select",
formatter: composeSelectFormatter(YOUR_DICTIONARY_RECORD_GOES_HERE),
values: [ ... ]
}
I just found myself in the same scenario.
I used a formatter function and tracked down the values in the list created in the column definition with the editorParams: {values:{1: "xxxx", 2:"xxxx"}},.
formatter: function(cell) {
let cgv = cell.getValue();
let values = cell?._cell?.column?.definition?.editorParams?.values;
console.dir(values);
if (cgv && values && values[cgv]) { return values[cgv]; }
//If you are using the combo {label: "", value: ""} you need to loop through the object
/*if (cgv && values && values.length) {
for (const v of values) {
if (v?.value == cgv && v?.label) { return v.label;}
}
}*/
return '';
}

jquery datatable - applying value for select.className is not working as expected

I am trying to change the background color of selected row(s) in jquery datatable using my own css class but, the tick mark in the checkbox is not appearing.
If I remove className: 'selected-row' from the below code, then everything works normal but, without the color I want.
Fiddler: https://jsfiddle.net/8f63kmeo/12/
HTML:
<table id="CustomFilterOnTop" class="table table-bordered table-condensed" width="100%"></table>
JS
var Report4Component = (function () {
function Report4Component() {
//contorls
this.customFilterOnTopControl = "CustomFilterOnTop"; //table id
//data table object
this.customFilterOnTopGrid = null;
//variables
this.result = null;
}
Report4Component.prototype.ShowGrid = function () {
var instance = this;
//create the datatable object
instance.customFilterOnTopGrid = $('#' + instance.customFilterOnTopControl).DataTable({
columns: [
{ title: "<input name='SelectOrDeselect' value='1' id='ChkBoxSelectAllOrDeselect' type='checkbox'/>" },
{ data: "Description", title: "Desc" },
{ data: "Status", title: "Status" },
{ data: "Count", title: "Count" }
],
"paging": true,
scrollCollapse: true,
"scrollX": true,
scrollY: "300px",
deferRender: true,
scroller: true,
dom: '<"top"Bf<"clear">>rt <"bottom"<"Notes">i<"clear">>',
buttons: [
{
text: 'Load All',
action: function (e, dt, node, config) {
instance.ShowData(10000);
}
}
],
columnDefs: [{
orderable: false,
className: 'select-checkbox text-center',
targets: 0,
render: function (data, type, row) {
return '';
}
}],
select: {
style: 'multi',
selector: 'td:first-child',
className: 'selected-row'
}
});
};
Report4Component.prototype.ShowData = function (limit) {
if (limit === void 0) { limit = 100; }
var instance = this;
instance.customFilterOnTopGrid.clear(); //latest api function
instance.result = instance.GetData(limit);
instance.customFilterOnTopGrid.rows.add(instance.result.RecordList);
instance.customFilterOnTopGrid.draw();
};
Report4Component.prototype.GetData = function (limit) {
//structure of the response from controller method
var resultObj = {};
resultObj.Total = 0;
resultObj.RecordList = [];
for (var i = 1; i <= limit; i++) {
resultObj.Total += i;
var record = {};
record.Description = "This is a test description of record " + i;
record.Status = ["A", "B", "C", "D"][Math.floor(Math.random() * 4)] + 'name text ' + i;
record.Count = i;
resultObj.RecordList.push(record);
}
return resultObj;
};
return Report4Component;
}());
$(function () {
var report4Component = new Report4Component();
report4Component.ShowGrid();
report4Component.ShowData();
});
function StopPropagation(evt) {
if (evt.stopPropagation !== undefined) {
evt.stopPropagation();
}
else {
evt.cancelBubble = true;
}
}
Issue:
Any suggestion / help will be greatly appreciated.
It's the class selected that sets the checkbox tick etc. and by using a different class the selected class is no longer added.
You can just add both those classes instead, and it should work
select: {
style: 'multi',
selector: 'td:first-child',
className: 'selected-row selected'
}
FIDDLE

Kendo Grid - Dont allow certain records for editing

I have the below command button column in my Kendo grid..
How to disable the "Edit" button in the rows with empty "ItemValue".
$("#list485").kendoGrid({
dataSource: dataSource,
columns: [
{ command: [{ name: "edit" }], title: " ", width: "100px"},
{ field: "ItemValue", title: "Item Description" }
],
editable: "popup"
});
you may hide edit button by on dataBound function as below
dataBound: function (e) {
var grid = $("#list485").data("kendoGrid");
var gridData = grid.dataSource.view();
for (var i = 0; i < gridData.length; i++) {
var currentUid = gridData[i].uid;
if (gridData[i].ItemValue == "") {
var currenRow = grid.table.find("tr[data-uid='" + currentUid + "']");
var editButton = $(currenRow).find(".k-grid-edit");
editButton.hide();
}
}
}
i hope this will help you
Not sure if this can fulfill your need but it works fine for inline editing.
$("#list485").kendoGrid({
dataSource: dataSource,
columns: [
{ command: [{ name: "edit" }], title: " ", width: "100px"},
{ field: "ItemValue", title: "Item Description" }
],
editable: "popup",
edit: function(e) {
if(e.model.ItemValue == 100)//your condition
{
$("#grid").data("kendoGrid").refresh();
}
}
});
Anyway this is what I could able to find till now.
There must be some better solution for this.

Empty a slickgrid in Javascript on a button click

Hello I have a slickgrid with five row , how can I empty my grid on a button click?
Thanks.
My grid code:
var grid;
var columns = [
{id: "title", name: "Title", field: "title"},
{id: "duration", name: "Duration", field: "duration"},
{id: "%", name: "% Complete", field: "percentComplete"},
{id: "start", name: "Start", field: "start"},
{id: "finish", name: "Finish", field: "finish"},
{id: "effort-driven", name: "Effort Driven", field: "effortDriven"}
];
var options = {
enableCellNavigation: true,
enableColumnReorder: false
};
$(function () {
var data = [];
for (var i = 0; i < 5; i++) {
data[i] = {
title: "Task " + i,
duration: "5 days",
percentComplete: Math.round(Math.random() * 100),
start: "01/01/2009",
finish: "01/05/2009",
effortDriven: (i % 5 == 0)
};
}
grid = new Slick.Grid("#myGrid", data, columns, options);
So to do what you intend to do, the following piece of code should work... Please note that I did not try it, I usually do a refresh of data instead, so try it and let me know:
// initialize the model after all the events have been hooked up
var data = null; // empty out your dataset
dataView.beginUpdate();
dataView.setItems(data);
dataView.endUpdate();
// re-render the grid
grid.updateRowCount();
grid.render();
EDIT
I just realized that you are not using a dataview object, I always use a dataview, it's easier to play with the data. So without the dataview, you could instead try doing this:
// reset the dataset
grid.setData(null, true);
// re-render the grid
grid.updateRowCount();
grid.render();
For the method documentation, see the wiki: SlickGrid grid.setData()

Categories

Resources