jsPDF-AutoTable generates a PDF table with empty cells - pdf

I want to generate a pdf from below HTML table, and I’m using jsPdf-AutoTable for that. I’m getting a PDF as below image. The table consist of correct number of rows without any data in it. How to get generate the pdf our of this table.?
I'm also using Datatable.js on this table.
HTML Table markup and Javascript given below.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"> </script>
<script src="https://github.com/MrRio/jsPDF/blob/master/dist/jspdf.debug.js"> </script>
<script src="https://github.com/simonbengtsson/jsPDF-AutoTable/blob/master/dist/jspdf.plugin.autotable.src.js"> </script>
// this function generates the pdf using the table
function generate() {
var columns = ["productid", "productname", "unit", "unitprice"];
var data = tableToJson($("#products-table").get(0), columns);
var doc = new jsPDF('p', 'pt');
doc.autoTable(columns, data);
doc.save("table.pdf");
}
// This function will return table data in an Array format
function tableToJson(table, columns) {
var data = [];
// go through cells
for (var i = 1; i < table.rows.length; i++) {
var tableRow = table.rows[i];
var rowData = {};
for (var j = 0; j < tableRow.cells.length; j++) {
rowData[columns[j]] = tableRow.cells[j].innerHTML;
}
data.push(rowData);
}
return data;
}
<table id="products-table" cellspacing="0" width="100%">
<thead>
<tr>
<th>ProductId</th>
<th>ProductName</th>
<th>Unit</th>
<th>UnitPrice</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
</tbody>
</table>
Run Code

It is because you are creating objects from table data. You should create an array from the data.
function tableToJson(table, columns) {
var data = [];
// go through cells
for (var i = 1; i < table.rows.length; i++) {
var tableRow = table.rows[i];
// create an array rather than an object
var rowData = [];
for (var j = 0; j < tableRow.cells.length; j++) {
rowData.push(tableRow.cells[j].innerHTML)
}
data.push(rowData);
}
return data;
}
check working fiddle
https://jsfiddle.net/shakee93/dh8e7gjc/

Related

In my Blazor server app, I have a problem when programming the rows of a table dynamically. What could be the problem?

I have following razor page in my Blazor server app (Code-1). In this razor page I have two dynamic tables. In the first table the CNC AX names of a CNC machine are listed (AX0...AX7). If the user clickes to the axis name, the axis parameters belonging to this axis shall be listed in the second table.
As result if I click to any axis name, I get always the parameters of the last axis (AX7) in the second table.
The axis parameters are read from the two dimension CNC_AX_MD array. I am sure that the array has the correct values for each axis, because if I write the first table like Code-2 (below) everything is working fine. But the number of axis are sometimes much more then in my code, so I have to shorten the code.
I think I have a problem on my dynamic table structure in table-1 with the for loop. What could be the problem? I have tried the act. commented out "StateHasChanged()" but it didn't help.
Code-1
<table>
#{ for (int j = 0; j < 8; j++)
{
<tr>
<td #onclick='#(e => Select_CNC_AX_par(j))'>#CNC_AX_Names[j]</td>
</tr>
//StateHasChanged();
}
}
</table>
<table>
#{ for (int m = 0; m < arraylenght; m++)
{
<tr>
<td >CNC_AX_parameter[m]</td>
</tr>
}
}
</table>
public void Select_CNC_AX_par(int aksno)
{
for(int k=0; k < arraylenght;k++)
{
CNC_AX_parameter[k] = CNC_AX_MD[k, axno];
}
}
Code-2
<table>
#{ <tr>
<td #onclick='#(e => Select_CNC_AX_par(0))'>#CNC_AX_Names[0]</td>
</tr>
<tr>
<td #onclick='#(e => Select_CNC_AX_par(1))'>#CNC_AX_Names[1]</td>
</tr>
<tr>
<td #onclick='#(e => Select_CNC_AX_par(2))'>#CNC_AX_Names[2]</td>
</tr>
<tr>
<td #onclick='#(e => Select_CNC_AX_par(3))'>#CNC_AX_Names[3]</td>
</tr>
<tr>
<td #onclick='#(e => Select_CNC_AX_par(4))'>#CNC_AX_Names[4]</td>
</tr>
<tr>
<td #onclick='#(e => Select_CNC_AX_par(5))'>#CNC_AX_Names[5]</td>
</tr>
<tr>
<td #onclick='#(e => Select_CNC_AX_par(6))'>#CNC_AX_Names[6]</td>
</tr>
<tr>
<td #onclick='#(e => Select_CNC_AX_par(7))'>#CNC_AX_Names[7]</td>
</tr>
}
</table>
Try to use the following code:
<table>
#{
for (int j = 0; j < 8; j++)
{
var Number = j;
<tr>
<td #onclick='#(e => Select_CNC_AX_par(Number))'>#j</td>
</tr>
//StateHasChanged();
}
}
</table>
Do not use a loop variable directly in a lambda expression, such as i in the preceding for loop example. Otherwise, the same variable is used by all lambda expressions, which results in use of the same value in all lambdas.
For more details,you can try to refer to the official doc.

Datables - hide data until search

I'd like for my page to initially load with just a search box, and then when someone begins to search that is when the table appears.
My example table is below:
<script>
$(document).ready(function() {
$('#example').DataTable( {
responsive: true
} );
} );
</script>
<table id="example" class="display" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th class="none">Branch</th>
</tr>
</thead>
<tbody>
<tr>
<td>Test 1</td>
<td>Test test test</td>
<td>ABC</td>
</tr>
<tr>
<td>Test 2</td>
<td>Test test test</td>
<td>DEF</td>
</tr>
<tr>
<td>Test 3</td>
<td>Test test test</td>
<td>GHI</td>
</tr>
</tbody>
</table>
yes it can be done using ajax call and i suppose you use php.
For example, you can generate a table everytime you press any char, populating the table with the results or using a button to search the keyword you type on the input field.
Example with ajax and php:
var search_string = $('#id_of_the_input_box').val();
$.ajax({
url:"php_file.php",
method:"POST",
data:{action:action},
dataType:"json",
success:function(data){
console.log(data);
}
and the php code using PDO
$search_string = $_POST["string"];
$result = '';
$query = $connection->prepare(" select * from table where name = '%".search_string."' ";
$query->execute();
$query_results->query->fetchAll;
if($query->rowCount() > 0) {
$result = '
<script>
$(document).ready(function() {
$('#example').DataTable( {
responsive: true
});
});
<table id="example" class="display" style="width:100%">
YOUR TABLE ROWS HERE
</table>
';
// foreach loop to populate the table example
foreach ($query_results as $row) {
$result.= '
<tr>
<td>'.$row["table_column_name_1"].'</td>
<td>'.$row["table_column_name_1"].'</td>
<td>'.$row["table_column_name_1"].'</td>
<td>'.$row["table_column_name_1"].'</td>
'
} else {
echo "No results";
}
}
// echo the generated table as ajax response
echo $result;
Hope you have caught the idea with this example.

Header row for editorfor template

I have a view in MVC4 that looks like this:
#model List<Home.Models.Model>
#{
ViewBag.Title = "DPR";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm("AgendaNotes", "Home", FormMethod.Post, new { #id = "formDPR"}))
{
<table style="font-size:xx-small">
<thead>
<tr>
<th>Name</th>
<th>DOD ID</th>
<th>Last Review</th>
<th>Include?</th>
<th>Reason</th>
<th>Notes</th>
</tr>
</thead>
</table>
<div style="background-color:white">
#Html.EditorForModel()
</div>
<div>
</div>
}
And the model.cshtml is simply some of the fields in a single row. I don't want to put headers on that single row as they are repeated as many times as their are in the list. Is there a simple way to make a header for the rows of the model in the editorfor template?
This is how I did it:
<table style="font-size:xx-small" class="table_body">
<thead>
<tr>
<th>Name</th>
<th>DOD ID</th>
<th>Last Review</th>
<th>Include?</th>
<th>Reason</th>
<th>Notes</th>
</tr>
</thead>
#for (var i = 0; i < Model.Count; i++)
{
<tr>
#Html.EditorFor(m=>Model[i])
</tr>
}
</table>
And in the model.cshtml it simple some of the fields each in a TD element.
Not 100% sure that I understand you correctly. Create the table header in the view, then call the EditorTemplate in a for each
#using (Html.BeginForm("AgendaNotes", "Home", FormMethod.Post, new { #id = "formDPR" }))
{
<table style="font-size:xx-small">
<thead>
<tr>
<th>Name</th>
<th>DOD ID</th>
<th>Last Review</th>
<th>Include?</th>
<th>Reason</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Details)
{
#testTemplate(item)
}
</tbody>
</table>
}
Then change the editor template to be for only one row eg.
#helper testTemplate(Details detail)
{
<tr>
<td>#detail.Propery1</td>
<td>#detail.Propery2</td>
</tr>
}
I used an inline helper just to illustrate what I mean. Now you should have a table with one header and lots of rows

Jquery DataTable date filter not working in client side

I am using Jquery DataTable in my MVC Application. I want to filter data in DataTable using Date-Range. when the page loads i am getting all the data from DB. so i need to implement this date range filter in one column of DataTable in client side. I have tried below coding but the date is not getting filtered.
HTML Table:
<table border="0" cellspacing="5" cellpadding="5">
<tbody>
<tr>
<td>From Date:</td>
<td><input type="text" id="min" name="min"></td>
</tr>
<tr>
<td>To Date:</td>
<td><input type="text" id="max" name="max"></td>
</tr>
</tbody>
</table>
<table id="Billing">
<thead>
<tr>
<th>Select</th>
<th>Company Name</th>
<th>Amount</th>
<th>Invoice Date</th>
<th>Status</th>
<th>Comments</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td><input type="checkbox" value=#item.companyId /></td>
<td> #item.CompanyName </td>
<td> #item.TotalAmount </td>
<td> #item.InvoiceDate </td>
<td> #item.Status </td>
<td> #item.Notes </td>
</tr>
}
</tbody>
</table>
jquery DataTable Initialize:
<script>
$(document).ready(function () {
$("#min").datepicker();
$("#max").datepicker();
var table = $('#Billing').dataTable(
{
"aLengthMenu": [[5, 10, 20, -1], [5, 10, 20, "All"]],
"iDisplayLength": 10
}).columnFilter({
sPlaceHolder: "head",
aoColumns: [null, null, null, { "type": "date-range" }, null, null]
});
// Event listener to the two range filtering inputs to redraw on input
$('#min, #max').keyup(function () {
table.draw();
});
});
$.fn.dataTable.ext.search.push(
function (settings, data, dataIndex) {
var dateMin = $('#min').attr("value");
var dateMax = $('#max').attr("value");
dateMin = dateMin.substring(0, 4) + dateRange.substring(5, 7) + dateRange.substring(8, 10);
dateMax = dateMax.substring(13, 17) + dateRange.substring(18, 20) + dateRange.substring(21, 23);
var date = aData[3];
// remove the time stamp out of my date
// 2010-04-11 20:48:22 -> 2010-04-11
date = date.substring(0, 10);
// remove the "-" characters
// 2010-04-11 -> 20100411
date = date.substring(0, 4) + date.substring(5, 7) + date.substring(8, 10)
// run through cases
if (dateMin == "" && date <= dateMax) {
return true;
}
else if (dateMin == "" && date <= dateMax) {
return true;
}
else if (dateMin <= date && "" == dateMax) {
return true;
}
else if (dateMin <= date && date <= dateMax) {
return true;
}
// all failed
return false;
}
);
</script>

Datatables plugin to search for header values

I am using jquery's dataTables plugin. I am having skills value as header in my table. I want to serch for users with specific skills. For example as shown in figure i want to search for users who have skill php. Then i should get the name of John. For css i should get name of Mona. The snapshot is here:
You can do this by implementing a custom filter for the datatable, as described here.
Before filtering you have to find, the index of the column you want to filter and check afterwards the value in each row.
This could look somewhat like this:
<input type="text" id="skillFilter" />
<table id="example">
<thead>
<tr>
<th>Skills</th>
<th>PHP</th>
<th>CSS</th>
<th>HTML</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>Mona</td>
<td>0</td>
<td>1</td>
<td>0</td>
</tr>
</tbody>
</table>
script :
$.fn.dataTable.ext.search.push(
function(settings, data) {
if (skillFilterColumnIndex != undefined) {
//Get the data of each row
var data = data[skillFilterColumnIndex] || "";
return data > 0;
} else {
return 1;
}
});
$("#skillFilter").change(function() {
var skill = $("#skillFilter").val().toLowerCase();
//Find the column index with the skill to filter
$.each($("#example thead th"), function(index, element) {
if (index != 0 && element.innerHTML.toLowerCase() == skill) {
skillFilterColumnIndex = index;
}
});
table.fnDraw();
});