DataTable losing fnCreatedCell after onClick event - javascript

Here is a fiddle that shows the problem: http://jsfiddle.net/LkqTU/32602/
If you go to the fiddle you will notice the last column is a link. If you click the checkbox on the first column you lose the link. I would like to keep the link.
I am creating the link in the DataTable like so...
{
data: 'dept',
"fnCreatedCell": function (nTd, sData, oData, iRow, iCol) {
$(nTd).html("<a href='Freight_ITN.aspx?scn=" + oData.dept + "' target='_blank'>" + "ITN ENTRY" + "</a>");
}
The onClick event of the checkbox is where I am losing my link (I think):
$('#mytable tbody').on('click', 'input[type="checkbox"]', function (e) {
var active = $(this).prop('checked');
var $row = $(this).closest('tr');
console.log($row);
var record = oTable.row($row).data();
record.active = active;
//console.log(record);
oTable.row($row).data(record).draw(false);
});
I noticed that DataTable has a fnDrawCallback, however it appears to be deprecated, and I'm unsure how to use it to get my link back.

You need add the rendering function to the column definitions configuration for your DataTable.
See the following example: http://jsfiddle.net/34ufp3ps/1/
columnDefs: [{
render: function(value, type, record, cellIndex) {
if (record.active) {
return value; // If selected, show the value instead of a link.
} else {
return '' + 'ITN ENTRY';
}
},
targets: 4 // Column #4 (Dept)
}]
Code
I made your class names Capitalized and added a convenience insert() method for proper OOP encapsulation of your Model object.
function Employee(id, firstName, lastName, dept, active, displayAsLink) {
var self = this;
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.dept = dept;
this.active = active;
this.displayAsLink = displayAsLink;
}
function EmployeeModel() {
var self = this;
this.employees = [];
}
EmployeeModel.prototype.insert = function(employee) {
this.employees.push(employee);
}
var myModel = new EmployeeModel();
$(document).ready(function() {
myModel.insert(new Employee('1', 'Clara', 'Dellinger', 'IT', false, true));
myModel.insert(new Employee('2', 'John', 'Smith', 'HR', false, true));
myModel.insert(new Employee('3', 'Fred', 'Jones', 'Finance', false, false));
myModel.insert(new Employee('4', 'Mary', 'Jans', 'Finance', false, false));
myModel.insert(new Employee('5', 'Bob', 'Jones', 'IT', false, false));
myModel.insert(new Employee('6', 'Fred', 'Thebes', 'HR', false, true));
myModel.insert(new Employee('7', 'Sally', 'Jane', 'HR', false, true));
myModel.insert(new Employee('8', 'Patrick', 'Roberts', 'HR', false, true));
myModel.insert(new Employee('9', 'Lisa', 'Myers', 'Lab', false, true));
myModel.insert(new Employee('10', 'Roscoe', 'Coletrain', 'Security', false, true));
var table = $('#mytable').DataTable({
data: myModel.employees,
columns: [{
data: 'active',
render: function(data, type, row) {
if (type === 'display') {
return '<input type="checkbox" class="editor-active">';
}
return data;
},
className: "dt-body-center"
}, {
data: 'id'
}, {
data: 'firstName'
}, {
data: 'lastName'
}, {
data: 'dept'
}],
columnDefs: [{
render: function(value, type, record, cellIndex) {
if (record.active) {
return value;
} else {
return '' + 'ITN ENTRY';
}
},
targets: 4 // Column #4 (Dept)
}],
rowCallback: function(row, data) {
// Set the checked state of the checkbox in the table
$('input.editor-active', row).prop('checked', data.active);
},
aaSorting: [
[3, 'asc']
],
});
$('#mytable tbody').on('click', 'input[type="checkbox"]', function(e) {
var active = $(this).prop('checked');
var $row = $(this).closest('tr');
var employee = table.row($row).data();
employee.active = active;
//console.log(employee);
table.row($row).data(employee).draw(false);
});
$.fn.dataTable.ext.search.push(
function(oSettings, aData, iDataIndex) {
var isSelected = aData[0];
var keywords = $("#mysearch").val().toLowerCase().split(' ');
var matches = 0;
for (var k = 0; k < keywords.length; k++) {
var keyword = keywords[k];
for (var col = 0; col < aData.length; col++) {
if (aData[col].toLowerCase().indexOf(keyword) > -1) {
matches++;
break;
}
}
}
return (matches == keywords.length) || (isSelected === 'true')
}
);
$('#mysearch').keyup(function() {
table.draw();
});
});
.dataTables_filter {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jasny-bootstrap/3.1.3/js/jasny-bootstrap.min.js"></script>
<script src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>
<script src="http://knockoutjs.com/downloads/knockout-3.2.0.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdn.datatables.net/1.10.12/css/jquery.dataTables.min.css" rel="stylesheet" />
<link href="http://cdnjs.cloudflare.com/ajax/libs/jasny-bootstrap/3.1.3/css/jasny-bootstrap.min.css" rel="stylesheet" />
<div>
<input type="text" id="mysearch" name="mysearch" placeholder="search" />
</div>
<table class="table" id="mytable">
<thead>
<tr>
<th>Select</th>
<th>Id</th>
<th>First</th>
<th>Last</th>
<th>Dept</th>
</tr>
</thead>
<tbody></tbody>
</table>

I just commented:
//table.row($row).data(employee).draw(true);
It is not necesssary to draw again in order to have the updated data.
employee.active = active;//this line updates the data.
You can add these two lines to verify:
e = table.row($row).data();
console.log(e);
The rendering function to the column definitions configuration for your DataTable is also correct.

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.

Limit checked , checkbox in bootstrap dataTable

I have this code below to click a checkbox in my DataTable and get the IDs and store in an array. For Example I have a 2 seperate DataTables First is for President and second is for the Senators.
We know that we can only vote 1 in President and for Senators we can choose many.
My problem here is I can check how many checkboxes in the DataTables. How to limit the checked checkboxes?.
Still learning in bootstrap here.
JS Code
var dataTablestest = $("#tbltest").DataTable({
responsive: true,
processing: true,
info: true,
search: true,
stateSave: true,
order: [[1, "asc"], [2, "asc"]],
lengthMenu: [[50, 100, 200, -1], [50, 100, 200, "All"]],
ajax: { "url": "/Voting/LoadTableTest" },
columns:
[
{ data: "testID", title: "", visible: false, searchable: false },
{ data: "Fullname", title: "FullName", sClass: "alignRight" },
{ data: "Position", title: "Position", sClass: "alignRight" },
{ data: "party", title: "Party", sClass: "alignRight" },
{ data: "ActionMenu", title: "Click to vote", searchable: false, orderable: false, sClass: "alignCenter",
"mRender": function (data) {
return '<center><label><input class="checkId" type="checkbox" id="chkvote_' + data + '" value=""/></label></center>';
}
}
]
});
var arrayIds = [];
$('#tbltest tbody').on('click', 'tr', function (e) {
if ($(e.target).is(".checkId")) {
var Ids = dataTablestest.row(this).data().testID;
arrayIds.push(Ids);
return
}
});
EDIT
I found an answer but there is a problem with it. My counter keeps increment every time I check a checkbox from my dataTable.
$('#tbltest tbody').on('click', 'tr', function (e) {
if ($(e.target).is(".checkId")) {
if ($(e.target).is(":checked") == true) {
CheckCount = CheckCount + 1;
var Ids = dataTablestest.row(this).data().testID;
if (CheckCount > 1) {
return false;
}
arrayIds.push(Ids);
return
}
else {
CheckCount = parseInt(CheckCount) - parseInt(1);
}
}
});
I use this code below.. Thanks to all who view my thread.
var arrayIds = [];
$('#tbltest tbody').on('click', 'tr', function (e) {
if ($(e.target).is(".checkId")) {
var Ids = dataTablestest.row(this).data().testID;
if ($(e.target).is(":checked") == true) {
var lenArray = arrayIds.length;
if (lenArray < 1) {
arrayIds.push(Ids);
} else {
return false;
}
}
else {
for (var i = arrayIds.length - 1; i >= 0; i--) {
if (arrayIds[i] === Ids) {
arrayIds.splice(i, 1);
}
}
}
}
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

Populate an iggrid combo box column on demand inside Editor dialog

I am attempting to load an editor dialog that contains a combo box. The combo box should be populated onload. the problem is that the combobox datasource doesn't get loaded the same time as the grid and when the data is finally fully populated from service the data is not intialized and displays an empty drop down list. I want to update the combobox columnSettings datasource when my data is returned from service.
I tried populating the combo box on the editRowStarted event? This worked but not for the initial display of the combo box.
<script>
var userDirectoryViewModel = #Html.Raw(Json.Encode(#Model));
</script>
<script id="dialogTemplate" type="text/html">
<div class="row-edit-dialog-container-head"><strong>${Name}</strong></div>
<div class="row-edit-dialog-container-cols">
<div style="float: left;">
<table>
<colgroup>
<col style="width: 30%;" />
<col style="width: 70%;" />
</colgroup>
<tbody data-render-tmpl="true"></tbody>
</table>
<button>Select</button>
</div>
#*<div style="width: 160px; float: right;">
<img width="100" height="90" src="${ImageUrl}" alt="${Name}" title="${Name}" style="float:right;" />
</div>*#
</div>
</script>
<script id="editorsTemplate" type="text/html">
<tr>
<td style="text-align:right;color:#777;"><strong>${headerText}</strong></td>
<td><input data-editor-for-${key}="true" /></td>
</tr>
</script>
<script type="text/javascript">
var mappingTypeList = [
{ Name: "GrantAdministratorRole", Number: "0" }, { Name: "GrantSupervisorRole", Number: "1" }, { Name: "MapToUserGroup", Number: "2" },
{ Name: "MapToTeam", Number: "3" }
];
//load on demand.
var mapToTeamList = [];
var mapToUserGroupList = [];
//Formatting for igGrid cells to display igCombo text as opposed to igCombo value
function formatMappingTypeCombo(val) {
var i, mappingType;
for (i = 0; i < mappingTypeList.length; i++) {
mappingType = mappingTypeList[i];
if (mappingType.Number == val) {
val = mappingType.Name;
}
}
return val;
}
function formatMapToUserGroupCombo(val) {
var i, userGroup;
for (i = 0; i < mapToUserGroupList.length; i++) {
userGroup = mapToUserGroupList[i];
if (userGroup.UserGroupID == val) {
val = userGroup.Name;
}
}
return val;
}
function formatMapToTeamCombo(val) {
var i, team;
for (i = 0; i < mapToTeamList.length; i++) {
team = mapToTeamList[i];
if (team.Number == val) {
val = team.Name;
}
}
return val;
}
function populateUserDirectoryMappings() {
console.log("calling populateUserDirectoryMappings()");
$.ajax({
type: "GET",
url: '/userdirectory/GetUserDirectoryMappings',
dataType: "json",
success: function (childData) {
mapToUserGroupList = childData.UserGroups;
mapToTeamList = childData.Teams;
return childData;
},
error:function() {
alert("error");
}
}).done(function(data) {
mapToUserGroupList = data.UserGroups;
});
}
function getUserGroups() {
var data = populateUserDirectoryMappings();
return data.UserGroups;
}
$( function () {
$("#groupMappingTable")
.igGrid({
dataSource: userDirectoryViewModel.GroupMappings,
primaryKey: "UserDirectoryGroupID",
width: "85%",
autoCommit: true,
autoGenerateColumns: false,
localSchemaTransform: false,
columns: [
{ headerText: "UserDirectoryGroupID", key: "UserDirectoryGroupID", dataType: "number", hidden: true },
{ headerText: "UserDirectoryID", key: "UserDirectoryID", dataType: "number", hidden: true },
{ headerText: "OrganizationID", key: "OrganizationID", dataType: "number", hidden: true },
{ headerText: "ExternalGroup", key: "Name", dataType: "string" },
{ headerText: "MappingType", key: "MappingType",formatter: formatMappingTypeCombo,width: "20%" },
{ headerText: "MapToUserGroup", key: "MapToUserGroup",formatter: formatMapToUserGroupCombo,width: "20%" },
{ headerText: "MapToTeam", key: "MapToTeam",formatter: formatMapToTeamCombo,width: "20%" }
],
rendered: function (evt, ui) {
},
features: [
{
name: "Updating",
enableAddRow: true,
enableDeleteRow: true,
editMode: "dialog",
columnSettings: [
{
columnKey: "OrganizationID",
readOnly: true
},
{
columnKey: "MappingType",
required:true,
editorType:"combo",
editorOptions: {
mode:"dropdown",
dataSource:mappingTypeList,
textKey:"Name",
valueKey:"Number"
}
},
{
columnKey: "MapToUserGroup",
required:false,
editorType:"combo",
editorOptions: {
mode:"dropdown",
id: 'mapToUserGroupComboID',
dataSource: mapToUserGroupList,
textKey:"Name",
valueKey:"UserGroupID"
}
},
{
columnKey: "UserDirectoryID",
readOnly: true
},
{
columnKey: "UserDirectoryGroupID",
readOnly: true
}
],
rowEditDialogOptions: {
width: "530px",
height: "410px",
dialogTemplateSelector: "#dialogTemplate",
editorsTemplateSelector: "#editorsTemplate",
showReadonlyEditors: false
},
rowAdding: function (evt, ui) {
ui.values["OrganizationID"] = userDirectoryViewModel.OrganizationID;
ui.values["UserDirectoryID"] = userDirectoryViewModel.UserDirectoryID;
},
rowAdded: function (evt, ui) {
console.log("row added event");
var ds = $("#groupMappingTable").igGrid("option", "dataSource");
},
editRowStarted: function(evt, ui) {
},
editRowEnded: function (evt, ui) {
//alert(ui.rowId);
}
}
]
});
});
</script>
I found the answer here api documentation
and I was then able to call into the grid and get the columnSettings object upon successfully retrieving the combo box data from the server.
function populateUserDirectoryMappings() {
console.log("calling populateUserDirectoryMappings()");
$.ajax({
type: "GET",
url: '/userdirectory/GetUserDirectoryMappings',
dataType: "json",
success: function(childData) {
mapToUserGroupList = childData.UserGroups;
mapToTeamList = childData.Teams;
return childData;
},
error: function() {
alert("error");
}
}).done(function(data) {
console.log("done");
console.log(data);
mapToUserGroupList = data.UserGroups;
var grid = $('#groupMappingTable').data('igGridUpdating');
var updating = grid.options.columnSettings;
console.log(updating);
console.log("map to user group list");
console.log(mapToUserGroupList);
$.each(updating, function(index, data) {
console.log("column");
console.log(data);
if (data.columnKey == "MapToUserGroup") {
data.editorOptions.dataSource = mapToUserGroupList;
}
});
});
}

jquery select2 add text to source if not found in source

I want select2 to behave as sort of combobox.See attached image for ref.
So if user types in a string but it is not found in source array, then on enter or closing select2 it should add that new string to source. So say if there were 2 values before, after above there would be now 3.
select2 just like combobox in file open dialogs
I have created sample code, but cant make it to work.I am unable to update source.
JSFIDDLE:
HTML:
<div class="row">
<div class="col-md-2">
<input type="hidden" id="select2_sample3" class="form-control ">
</div>
</div>
JS:
$(function () {
var preload_data = {
results: [{
id: 'user0',
text: 'Disabled User',
}, {
id: 'user1',
text: 'Jane Doe'
}]
};
$("#select2_sample3").select2({
placeholder: "Select...",
allowClear: true,
minimumInputLength: 1,
data: preload_data,
query: function (query) {
var data = {
results: []
}, i, j, s;
for (i = 1; i < 5; i++) {
s = "";
for (j = 0; j < i; j++) {
s = s + query.term;
}
data.results.push({
id: query.term + i,
text: s
});
}
query.callback(data);
}
}).on("select2-close", function () {
// add to
console.log("close");
});
});
I've recently had the same task. This is my solution:
<input type="hidden" name="trBrand" id="trBrand" class="form-control"></input>
and js code
$('#trBrand').select2({
placeholder: 'choose something',
allowClear: true,
id: function(object) {
return object.text;
},
createSearchChoice:function(term, data) {
if ( $(data).filter( function() {
return this.text.localeCompare(term)===0;
}).length===0) {
return {id:term, text:term};
}
},
data:preload_data
});

Categories

Resources