How to get parameter from another datatable column? - javascript

My objective is to carry multiple parameters in same row but from different column. In my case, each row contain of 7 columns. but only 3 parameters that I need to pass to btnApprove1 function. This function will appoint to other API which require all that 3 parameters.
So how to carry service_id, project_id and staff_id into btnApprove function when clicked?
columns: [
{ data : "service_id", "className": "text-center" },
{ data : "project_id", "className": "text-center" },
{ data : "staff_id", "className": "text-center" },
{ data : "status", "className": "text-center",
render: function(data){
if (data == "1001") {
return "<span onclick='btnApprove(""+data+"")'</span>";
}
else {
return data;
}
}
},
{ data : "lorry", "className": "text-center" },
{ data : "car", "className": "text-center" },
{ data : "van", "className": "text-center" }
]
function btnApprove(service_id, project_id, staff_id){
console.log(service_id, project_id, staff_id)
var params = {
"service_id": service_id,
"project_id": project_id,
"staff_id": staff_id
};
params = JSON.stringify(params);
$.ajax ({
...
});
}

According to the jQuery Datatable documentation for the column cell render() function, it takes four parameters, the third parameter is called row, and it's an array of values each representing the value of the column with the respective index. You can use this parameter to pass the right values to your btnApprove function.
In the code block below, I make use of destructuring on the row array to only get the first three values you need. Template literals also help make string HTML more readable.
render: function(data, type, [service_id, project_id, staff_id]) {
if (data === '1001') {
return `
<span onclick="btnApprove('${service_id}', '${project_id}', '${staff_id}')">
${data}
</span>
`;
}
return data;
}
To make sure that your <span> click event has access to btnApprove when used as a string like you have, it needs to be declared globally, on thing you can do is to change the definition of the function from:
function btnApprove(service_id, project_id, staff_id) {
To:
btnApprove = function(service_id, project_id, staff_id) {

I just solve this issue by applying this.
{ data : "status", "className": "text-center",
fnCreatedCell: function (nTd, sData, oData, iRow, iCol) {
if (oData.status == "1001") {
var stat = '<span class="badge badge-warning font-11">Approval</span><br/>';
$(nTd).html("<span onclick='btnApprove(""+oData.service_id+"", ""+oData.project_id+"", ""+oData.staff_id+"")'>"+stat+"</span>");
}
else if (oData.status == "1000") {
var stat2 = '<span class="badge badge-primary font-11">Registered</span>';
$(nTd).html("<span onclick='btnNotApprove(""+oData.service_id+"", ""+oData.project_id+"", ""+oData.staff_id+"")'>"+stat2+"</span>");
}
}
},

Related

How can I bind data from db (jQuery) to an autocomplete?

I try to bind the data from a database tabel to an autocomplete edit field.
But somehow I don't succeed and need help.
I have the data on another webpage already in a dropdown combo. How can I access this data or replicate the funcionality for the edit field?
Thx for any hint.
-Adrian
I want the data from the db show up where I am using the country arry right now:
/*An array containing all the country names in the world:*/
var countries = ["Afghanistan","Albania","Algeria","Andorra","Angola","Anguilla","Antigua & Barbuda","Argentina","Armenia","Aruba","Australia","Austria","Azerbaijan","Bahamas","Bahrain","Bangladesh","Barbados","Belarus","Belgium","Belize","Benin","Bermuda","Bhutan","Bolivia",...];
/*initiate the autocomplete function on the "myInput" element, and pass along the countries array as possible autocomplete values:*/
autocomplete(document.getElementById("myInput"), countries);
</script>
And to get the code from the database the following code seems to be used in another file of the project:
/**
* Loads skills into the table.
* #param {array} skills An array of skills.
*/
loadTable: function(skills) {
if(typeof skills != "object") skills = [];
if ( $.fn.dataTable.isDataTable( '#dyn_skills' ) ) {
$('#dyn_skills').DataTable().destroy();
}
var t = $("table.skills");
// remove tr elements which do not have
// the class "head", "template" or "status"
$("tr:not(.head,.template,.status)", t).remove();
// no skills found
if(! skills.length) {
$("tr.status td", t).empty().append(_("No skills found."));
$("tr.status td", t).show();
} else {
$("tr.status", t).remove();
}
if(skills.length) {if ( $.fn.dataTable.isDataTable( '#dyn_skills' ) ) {
DynTable = $('#dyn_skills').DataTable();
}
else {
DynTable = $('#dyn_skills').DataTable( {
"data" : skills,
"columns" : [
{ "data" : "id", "title" : _("Id") },
{ "data" : "preferredLabel" , "title" : _("Name") },
{ "data" : "description" , "title" : _("Description") }
],
"lengthMenu": [ 5, 10, 25, 50],
stateSave: true,
"language": {
"decimal": "",
"emptyTable": _("No data available in table"),
"info": _("Showing _START_ to _END_ of _TOTAL_ entries"),
"infoEmpty": _("Showing 0 to 0 of 0 entries"),
"infoFiltered": _("(filtered from _MAX_ total entries)"),
"infoPostFix": "",
"thousands": ",",
"lengthMenu": _("Show _MENU_ entries"),
"loadingRecords": _("Loading..."),
"processing": _("Processing..."),
"search": _("Search:"),
"zeroRecords": _("No matching records found"),
"paginate": {
"first": _("First"),
"last": _("Last"),
"next": _("Next"),
"previous": _("Previous")
},
"aria": {
"sortAscending": _(": activate to sort column ascending"),
"sortDescending": _(": activate to sort column descending")
}
}
} );
//read from url parameter and set datatables search value
$.urlParam = function(name){
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
if (results==null) return null;
else return results[1] || 0;
}
var datatablesfilter = $.urlParam('datatablesfilter');
if(datatablesfilter == null) DynTable.search("").draw();
else DynTable.search(datatablesfilter).draw();
}
}
// On click the selected row gets the class "selected_row"
// The class "selected_row" is highlighted via CSS
// and used as a row selection marker for performing any action "edit" or "delete"
$('#dyn_skills tbody').on( 'click', 'tr:not(.status)', function () {
$("table#dyn_skills tr.selected_row").removeClass('selected_row');
$(this).addClass('selected_row');
event.stopPropagation();
} );
// binding event button #button_edit
// Read the data from the marked row and call the API function
$("button#button_edit").click( function () {
if (! $("table#dyn_skills tr.selected_row").length ){
alert(_("Please select a row from the table!!!"));
}
else
{
var skill_id = $("table#dyn_skills tr.selected_row td:eq(0)").text();
var skill_name = $("table#dyn_skills tr.selected_row td:eq(1)").text();
var skill_description = $("table#dyn_skills tr.selected_row td:eq(2)").text();
KPP.loadDialog(".template.skill-edit-dialog", null, function(self) {
$(".skill-id", self).empty().append(skill_id);
$(".skill-name", self).val(skill_name);
$(".skill-description", self).empty().append(skill_description);
$(".skill-send", self).click(function() {
KPP.Skill.edit(skill_id, {
"name": $(".skill-name", self).val(),
"description": $(".skill-description", self).val()
});
});
$(".skill-name", self).focus(); // set focus
});
}
} ); // end of button_edit

How do I programmatically remove a custom action button in a Tabulator table?

I created a Tabulator table which has a custom action button to execute an action and then updates the row on which the button was clicked. This it does successfully.
What I want to do is to also dynamically remove the row's link/buttonthat was clicked - only for the row whose button was clicked - as soon as the row data is updated. I've tried to resolve this for hours and checked the tabulator documentation, and I still don't know how I can go about doing this.
Your help is much appreciated.
The code is as follows:
var tableData =[
{
"id":30,
"position":201,
"category":"onel",
"name":"One Thing",
"completed_at":null,
"created_by_email":"",
"completed_by":""
},
{
"id":31,
"position":202,
"category":"onel",
"name":"Two things",
"completed_at":null,
"created_by_email":"",
"completed_by":""
},
{
"id":32,
"position":203,
"category":"onel",
"name":"Three things",
"completed_at":null,
"created_by_email":"",
"completed_by":""
},
{
"id":33,
"position":204,
"category":"onel",
"name":"Four things",
"completed_at":null,
"created_by_email":"",
"completed_by":""
},
{
"id":34,
"position":205,
"category":"onel",
"name":"Five things",
"completed_at":null,
"created_by_email":"",
"completed_by":""
}
];
var actButton = (cell, params, onRendered) => {
var myId = cell.getRow().getData().id;
clickFunction = (p_id) => {
cell.getTable().updateData(
[
{ id: p_id
, completed_at: '2021-12-31 13:59:00'
, completed_by: 'Womble'
, completed_by_email: 'wimbledon#common.org.uk'
}
]
// <--- here, I want to remove this row's action button as defined below
);
};
/**
* This renders the buttons at initialisation but doesn't respond to dynamic in-situ data-changes
*/
if ( null == cell.getRow().getData().completed_at ) {
return "<a href='javascript: clickFunction(" + myId + ")' data-toggle='tooltip' title='Execute'><i class='fas fa-camera' style='color:#9691ce;'></i></a>";
} else {
return "";
}
};
var myTable = new Tabulator(
"#divTable",
{
data: tableData,
columns: [
{title:"Position", field:"position"},
{title:"Category", field:"category"},
{title:"Name", field:"name"},
{title:"Completed", field:"completed_at", formatter:"datetime", formatterParams:{inputFormat:"YYYY_MM_DD HH:mm:ss", outputFormat:"DD/MM/YYYY HH:mm:ss", invalidPlaceholder:""} },
{title:"By", field:"completed_by", sorter:"string"},
{title:"Email", field:"completed_by_email", sorter:"string"},
{title:"Action", field:"id", sortable:false, formatter:actButton},
],
layout: "fitColumns",
pagination: "local",
paginationSize: "15",
tooltips:true,
tooltipsHeader:true,
reactiveData:true, //turn on data reactivity
}
);
I was looking to the Tabulator component object model for the solution, when it was best answered by the DOM.
Assumptions:
the action button column is assigned the field 'id' - this doesn't affect the dynamic table's layout or interaction
Using a fragment of the above code as a starting point, the solution would be:
var actButton = (cell, params, onRendered) => {
var myId = cell.getRow().getData().id;
clickFunction = (p_id) => {
cell.getTable().updateData(
[
{ id: p_id
, completed_at: '2021-12-31 13:59:00'
, completed_by: 'Womble'
, completed_by_email: 'wimbledon#common.org.uk'
}
]
).then (
() => {
/**
* Remove the action button
*/
[...document.querySelectorAll("div.tabulator-cell")]
.filter(item => item.getAttribute('title')==p_eventId)[0]
.childNodes[0].remove();
}
);
};
/**
* This renders the buttons at initialisation but doesn't respond to dynamic in-situ data-changes
*/
if ( null == cell.getRow().getData().completed_at ) {
return "<a href='javascript: clickFunction(" + myId + ")' data-toggle='tooltip' title='Execute'><i class='fas fa-camera' style='color:#9691ce;'></i></a>";
} else {
return "";
}
};

Add json data to datatables

I am trying to populate datatables with a complex json scheme, however I don't know exactly how to do it.
First, some parts of json are nested and it needs iteration.
Second I need to create some markup, basically a href link.
Here is what I have:
$(document).ready(function(){
$('#empTable').DataTable({
'processing': true,
'serverSide': true,
'serverMethod': 'post',
'ajax': {
'url':'/dashboard/ajaxgetrequests',
dataSrc: "json_list"
},
'columns': [
{ data: 'firstname' },
{ data: 'funding_project_name' } // this must be a link like <a href='/<relation_id>'><funding_project_name></a>
]
});
});
{
"json_list":{
"125":{
"firstname":"John",
"funding_project_name":"A",
"relation_id": "7"
},
"133":{
"firstname":"Cesar",
"funding_project_name":[
"A",
"B"
],
"relation_id":[
"7",
"9"
]
}
}
}
1) For nested JSON you can use something like this:
// JSON structure for each row:
// {
// "engine": {value},
// "browser": {value},
// "platform": {
// "inner": {value}
// },
// "details": [
// {value}, {value}
// ]
// }
$('#example').dataTable( {
"ajaxSource": "sources/deep.txt",
"columns": [
{ "data": "engine" },
{ "data": "browser" },
{ "data": "platform.inner" },
{ "data": "details.0" },
{ "data": "details.1" }
]
} );
2) To edit and insert a link you can use columns.render (documentation)
$('#example').dataTable( {
"columnDefs": [ {
"targets": 0,
"data": "download_link",
"render": function ( data, type, row, meta ) {
return 'Download';
}
} ]
} );
Honestly, there may be a better built in way of handling this but when I experience things that do not fit the exact mold of using the base datatable functionality, I prefer to take manual control of the generation. This will give you an overview on how to do it with your structure:
Just basic html for your table (nothing really to see here):
<table id="empTable">
<thead>
<tr><th>First Name</th><th>ProjectName</th></tr>
</thead>
<tbody></tbody>
</table>
In JS we declare a variable we can use throughout our script then on ready event we instatiate our datatable:
var dt;
$(document).ready(function () {
dt = $('#empTable').DataTable();
loadDT();
});
We will also use a function call 'loadDT()' and what this will do is trigger a ajax call to the backend to get your json, in this example, I'm just gonna mock it but in your world so this on the ajax success:
Iterate your list and determine the types then use the api call row.add to dynamically add new rows to your table. (notice we are reusing the stored variable dt that we initially declared.) This is where you can do whatever custom logic fun you need to do.
function loadDT(){
var mockJSON = { "json_list":{ "125":{ "firstname":"John","funding_project_name":"A","relation_id": "7"},"133":{ "firstname":"Cesar","funding_project_name":["A","B"],"relation_id":["7","9"]}}};
$.each(mockJSON.json_list, function (i, n){
if(Array.isArray(n.funding_project_name)) {
$.each(n.funding_project_name, function (i2, p){
dt.row.add([n.firstname,'' + p + '']);
dt.draw(false);
});
} else {
dt.row.add([n.firstname, '' + n.funding_project_name + '']);
dt.draw(false);
}
});
}
Like previously stated, there may be some built in functions to handle this that I am unaware but when things get complicated, just know you can take manual control of it.
Full Example:
var dt;
$(document).ready(function () {
dt = $('#empTable').DataTable();
loadDT();
});
function loadDT(){
var mockJSON = { "json_list":{ "125":{ "firstname":"John","funding_project_name":"A","relation_id": "7"},"133":{ "firstname":"Cesar","funding_project_name":["A","B"],"relation_id":["7","9"]}}};
$.each(mockJSON.json_list, function (i, n){
var projLinks = "";
if(Array.isArray(n.funding_project_name)) {
$.each(n.funding_project_name, function (i2, p){
projLinks += '' + p + ' ';
});
} else {
projLinks = '' + n.funding_project_name + '';
}
dt.row.add([n.firstname, projLinks]);
dt.draw(false);
});
}
<link href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<table id="empTable">
<thead>
<tr><th>First Name</th><th>ProjectName</th></tr>
</thead>
<tbody></tbody>
</table>

What I m missing to implement case insensitive search?

Here is my js file. I 've done everything in the server side. And implemented all basic and some advance feature of Datatable plugins. But the search function is case sensitive. If I search for "oil" it shows oil only but not OIL.
$(document).ready(function () {
var oTable = $('#myDataTable').dataTable({
"bServerSide": true,
"sPaginationType": "full_numbers",
"sAjaxSource": "/DB/AjaxOil",
"bProcessing": true,
"Search": {
"caseInsensitive": true
},
"aoColumns": [
{
"sName": "OilId",
"aTargets": [0], //Edit column
"mData": "OilId",
"bSearchable": false,
"bSortable": false,
"mRender": function (data, type, full) {
var id = full[0]; //row id in the first column
return "<a>"+id+"</a>";
}
},
{ "sName": "CommonName" },
{ "sName": "BotanicalName" },
{ "sName": "PlantParts" },
{ "sName": "Distillation" }
],
"columnDefs": [
{
"targets": [0],
className: "hide_column",
"searchable": false
}
]
});
});
And Here is my ajax function
public ActionResult AjaxOil(JQueryDataTableParamModel param)
{
IEnumerable<Oil> allOils = _context.Oils.ToList();
IEnumerable<Oil> filteredOils;
if (!string.IsNullOrEmpty(param.sSearch))
{
filteredOils = allOils
.Where(c => c.CommonName.Contains(param.sSearch)
||
c.BotanicalName.Contains(param.sSearch)
||
c.PlantParts.Contains(param.sSearch)
||
c.Distillation.Contains(param.sSearch));
}
else
{
filteredOils = allOils;
}
var sortColumnIndex = Convert.ToInt32(Request["iSortCol_0"]);
Func<Oil, string> orderingFunction = (c => sortColumnIndex == 1 ? c.CommonName :
sortColumnIndex == 2 ? c.BotanicalName :
c.PlantParts);
var distillationFilter = Convert.ToString(Request["sSearch_4"]);
var commonFilter = Convert.ToString(Request["sSearch_1"]);
var botanicalFilter = Convert.ToString(Request["sSearch_2"]);
var plantFilter = Convert.ToString(Request["sSearch_3"]);
if (!string.IsNullOrEmpty(commonFilter))
{
filteredOils = filteredOils.Where(c => c.CommonName.Contains(commonFilter));
}
if (!string.IsNullOrEmpty(botanicalFilter))
{
filteredOils = filteredOils.Where(c => c.BotanicalName.Contains(botanicalFilter));
}
if (!string.IsNullOrEmpty(plantFilter))
{
filteredOils = filteredOils.Where(c => c.PlantParts.Contains(plantFilter));
}
if (!string.IsNullOrEmpty(distillationFilter))
{
filteredOils = filteredOils.Where(c => c.Distillation.Contains(distillationFilter));
}
var sortDirection = Request["sSortDir_0"];
if (sortDirection == "asc")
filteredOils = filteredOils.OrderBy(orderingFunction);
else
filteredOils = filteredOils.OrderByDescending(orderingFunction);
var displayedOils = filteredOils
.Skip(param.iDisplayStart)
.Take(param.iDisplayLength);
var result = from c in displayedOils
select new[] { Convert.ToString(c.OilId), c.CommonName, c.BotanicalName, c.PlantParts, c.Distillation };
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = allOils.Count(),
iTotalDisplayRecords = filteredOils.Count(),
aaData = result
},
JsonRequestBehavior.AllowGet);
}
P.s. The database has 5million row so please suggest with performance point of view too.
First of all you should not use _context.Oils.ToList(); then you will retrieve all your records from the database before filtering them. If you place the ToList() after .Take(param.iDisplayLength) all your selection code will be translated to a query in your database and only the relevant records will be retrieved. There is a difference between Contains executed by the Linq extension (case sensitve; see also this SO question) and the Contains that will we translated by the Entity Framework to a LIKE SQL statement (see this SO question and this video about tracing the SQL statements generated by your code).
As Shyju mentioned, refer to this post:
Case insensitive 'Contains(string)'
This will give you a wholistic idea of what to expect.
Here is a small excerpt from the post for your reference:
To test if the string paragraph contains the string word (thanks #QuarterMeister)
culture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0
Where culture is the instance of CultureInfo describing the language that the text is written in.
In addition, I encourage you to visit this article which has an exhaustive comparison of various methods’ performances while checking if a string occurs within a string. This should help you decide what approach to take for better performance.
http://cc.davelozinski.com/c-sharp/fastest-way-to-check-if-a-string-occurs-within-a-string
Based on your question, you may have to create an extension method which will use different approach to preform check based on the type of input to achieve best performance.
Hope this helps!

Case insensitive search in search2.js

I am using select2.js in my project for drop down functionality. By default behaviour this is case sensitive i.e tag and Tag will be consider different.
But as per my requirement i required result populate is case insensitive i.e. when writing tag or Tag both need to considered to be small like in capital. I have tried many solution for this but non of that seems to working. I need to deal this client side only.
Issue is like this "https://groups.google.com/forum/#!topic/select2/vk86jUMfJTk"
$('#Taging').select2({
tags : true,
tokenSeparators : [ ',' ],
createSearchChoice : function(term) {
return {
id : term,
text : term,
n : "new",
s : ""
};
},
ajax : {
},
// Take default tags from the input value
initSelection : function(element, callback) {
var data = [];
$(splitVal(element.val(), ",")).each(function() {
data.push({
id : this,
text : this
});
});
callback(data);
},
});
sample Code
I modified my code and that works
createSearchChoice : function(term,data) {
if (term.trim().length > 0) {
if ($(data).filter(function () {
return this.text.toLowerCase().localeCompare(term.toLowerCase()) === 0;
}).length === 0) {
return {
id: term,
text: term,
n : "new",
s : "",
isNew: true // this is necessary to check if the item is newly added or not
};
}
}
},

Categories