MVC Creating a PDF file for one table row - javascript

I have a problem with adding a button that will generate a PDF file for a specific table row. I can do this for whole table but not for a specific row.
My "Execute" view (create PDF file for entire table):
<div id="Grid">
<table class="table table-hover table-bordered" id="ExeTable">
<thead>
<tr>
<th class="text-center">Order nr</th>
<th class="text-center">Mat nr</th>
<th class="text-center">SAP nr</th>
<th class="text-center">Batch nr</th>
<th class="text-center">Tank</th>
</tr>
</thead>
<tbody id="myTable">
#foreach (var item in Model.ib)
{
<tr>
<td class="text-center">#item.OrderNr</td>
<td class="text-center">#item.MatNr</td>
<td class="text-center">#item.SapNr</td>
<td class="text-center">#item.BatchNr</td>
<td class="text-center">#item.TankName</td>
</tr>
}
</tbody>
</table>
</div>
#using (Html.BeginForm("Export", "Order", FormMethod.Post))
{
<input type="hidden" name="GridHtml" />
<input type="submit" id="btnSubmit" value="Export" />
}
<script>
$(function (print) {
$("#btnSubmit").click(function () {
$("input[name='GridHtml']").val($("#Grid").html());
});
});
</script>
But I want to have a new column in the table where there will be a button to generate a PDF for a specific row. I tried something but without success.
// I tried this
<table class="table table-hover table-bordered" id="ExeTable">
<thead>
<tr>
<th>Create PDF</th>
<th class="text-center">Order nr</th>
<th class="text-center">Mat nr</th>
<th class="text-center">SAP nr</th>
<th class="text-center">Batch nr</th>
<th class="text-center">Tank</th>
</tr>
</thead>
<tbody id="myTable">
#foreach (var item in Model.ib)
{
<tr>
<td class="text-center">
#using (Html.BeginForm("Export", "Order", FormMethod.Post))
{
<input type="hidden" name="GridHtml" />
<input type="submit" id="btnSubmit" value="Export" />
}
</td>
<td class="text-center">#item.OrderNr</td>
<td class="text-center">#item.MatNr</td>
<td class="text-center">#item.SapNr</td>
<td class="text-center">#item.BatchNr</td>
<td class="text-center">#item.TankName</td>
</tr>
}
</tbody>
</table>
My method that generete PDF file in "Order" controller:
[HttpPost]
[ValidateInput(false)]
public FileResult Export(string GridHtml)
{
using (MemoryStream stream = new System.IO.MemoryStream())
{
StringReader sr = new StringReader(GridHtml);
Document pdfDoc = new Document(PageSize.A4);
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, stream);
pdfDoc.Open();
XMLWorkerHelper.GetInstance().ParseXHtml(writer, pdfDoc, sr);
pdfDoc.Close();
return File(stream.ToArray(), "application/pdf", "Grid.pdf");
}
}

Your initial example pulls the inner contents of the Grid element. There does not appear to be a surrounding identifiable element from which to pull the contents for a row. A simple fix would be to add an id to each row, change the button id to a class to add the eventlistener, and add a data- attribute to hold info on which row was clicked:
#foreach (var item in Model.ib)
{
<tr id="#item.OrdrNr">
<td class="text-center">
#using (Html.BeginForm("Export", "Order", FormMethod.Post))
{
<input type="hidden" name="GridHtml" />
<input type="submit" class="btnSubmit" data-row="##item.OrdeNr" value="Export" />
}
</td>
<td class="text-center">#item.OrderNr</td>
<td class="text-center">#item.MatNr</td>
<td class="text-center">#item.SapNr</td>
<td class="text-center">#item.BatchNr</td>
<td class="text-center">#item.TankName</td>
</tr>
}
And the JavaScript:
$(".btnSubmit").click(function (event) {
var target = $(event.currentTarget).data('row');
$("input[name='GridHtml']").val($(target).html());
});
What this will send to your Controller is just the contents of the clicked row:
<td class="text-center">
#using (Html.BeginForm("Export", "Order", FormMethod.Post))
{
<input type="hidden" name="GridHtml" />
<input type="submit" class="btnSubmit" data-row="##item.OrdeNr" value="Export" />
}
</td>
<td class="text-center">#item.OrderNr</td>
<td class="text-center">#item.MatNr</td>
<td class="text-center">#item.SapNr</td>
<td class="text-center">#item.BatchNr</td>
<td class="text-center">#item.TankName</td>
In the controller, you can remove the button, wrap that in the rest of your table tags, and then convert to PDF.

Related

Dynamically added table data and table rows have zero height

I am using angular.element to dynamically inject table data into my table. Onload my table already has data, when I double click on the content it hides the old tbody and shows the new tbody where the dynamic data needs to be added and this tbody contains a form as well to send the edited data.
here's the html:
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<td class="text-center"><b>Code</b></td>
<td class="text-center"><b>Particulars</b></td>
<td class="text-center"><b>Amount(Rs. in lakh)</b></td>
</tr>
</thead>
<tbody ng-if="loading == false && iseditstmt == false">
<tr ng-repeat="b in blsheetinfo">
<td class="text-left"><b>{{b.key}}</b></td>
<td class="text-left">{{b.particular}}</td>
<td class="text-right" ng-dblclick="editstmt();editRec(blsheetinfo,'edit','stmtupdate');">{{b.amt}}</td>
</tr>
<tr ng-if="blsheetinfo == null">
<td class="text-center" colspan="3">No data found.</td>
</tr>
</tbody>
<tbody ng-if="iseditstmt == true">
<form role="form" ng-submit="updatestmt(data)" name="updatedata" id="updatedata" >
</form>
</tbody>
<tr ng-if="loading == 1"><td class="text-center" colspan="3">Loading...</td></tr>
</table>
This is the js code:
var HTMLcontent = "";
angular.forEach($scope.blsheetinfo, function (d) {
HTMLcontent += `<tr class="form-group">
<td class="text-left " ng-model="frmdata.key" name="key" id="key" ><b> `+d.key+`</b></td>
<td class="text-left" ng-model="frmdata.particular" name="particular" id="particular" >`+d.particular+`</td>
<td class="text-right" ng-model="frmdata.amt" name="amt" id="amt" ><input class="form-control" type="text">`+d.amt+`</td>
</tr>`
});
setTimeout(function(
)
{
// angular.element("#updatedata").html(HTMLcontent);
// tried both of these options
angular.element("#updatedata").append(HTMLcontent);
},2000);
The problems that I am facing are that it looks like my data is being added to the DOM but i am not able to see it. The tbody element has height set to 0

Ajax append one row instead of array

I have an ajax function that gets an array of data from the backend and when I try to append those data in the blade it only shows 1 row instead of an array of rows.
Issues
Only 1 row append by ajax
Select option will be empty when results return while I don't have any code to clear my select option.
Code
$(function() {
// get cities
$('#province').on('change', function(e) {
e.preventDefault();
$.ajaxSetup({
headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }
});
var hospitalId = $(this).val();
$.ajax({
url: '{{ url('hospitals') }}/'+encodeURI(hospitalId),
dataType: "json",
type: 'GET',
success: function(data) {
console.log('dd: ', data.data);
if(data.data != null) {
$('.resError').hide();
$('.result').show();
// data to append
$.each(data.data, function(key, value) {
$('#code').html(value.code);
$('#name').html(value.name);
$('#type').html(value.type);
$('#class').html(value.class);
$('#beds').html(value.beds);
$('#owner').html(value.owner);
$('#province').html(value.province);
$('#city').html(value.city);
$('#address').html(value.address);
});
} else {
$('.resError').show();
$('.result').hide();
$('.resError').html('something went wrong, try again!');
}
},
error:function(err) {
$('.resError').show();
$('.resError').html('You need to select province!');
$('.result').hide();
$('#code').html('');
$('#name').html('');
$('#type').html('');
$('#class').html('');
$('#beds').html('');
$('#owner').html('');
$('#province').html('');
$('#city').html('');
$('#address').html('');
}
});
});
});
results
Update
<p>Results</p>
<div class="resError clearfix mt-4" style="display:none;"></div>
<div class="result clearfix mt-4" style="display:none;">
<table class="mb-3 table table-bordered table-hover">
<tbody>​​​
<tr>
<th width="50">Code</th>
<td id="code"></td>
</tr>
<tr>
<th width="50">Name</th>
<td id="name"></td>
</tr>
<tr>
<th width="50">Type</th>
<td id="type"></td>
</tr>
<tr>
<th width="50">Class</th>
<td id="class"></td>
</tr>
<tr>
<th width="50">Beds</th>
<td id="beds"></td>
</tr>
<tr>
<th width="50">Owner</th>
<td id="owner"></td>
</tr>
<tr>
<th width="50">Province</th>
<td id="province"></td>
</tr>
<tr>
<th width="50">City</th>
<td id="city"></td>
</tr>
<tr>
<th width="50">Address</th>
<td id="address"></td>
</tr>
</tbody>
</table>
</div>
in blade
<p>Results</p>
<div class="resError clearfix mt-4" style="display:none;"></div>
<div class="result clearfix mt-4" style="display:none;">
<table class="mb-3 table table-bordered table-hover">
<tbody id="body">​​​
</tbody>
</table>
</div>
in javascript
$.each(data.data, function(key, value) {
var element = `
<tr>
<th width="50">Code</th>
<td id="code">${value.code}</td>
</tr>
<tr>
<th width="50">Name</th>
<td id="name">${value.name}</td>
</tr>
<tr>
<th width="50">Type</th>
<td id="type">${value.type}</td>
</tr>
<tr>
<th width="50">Class</th>
<td id="class">${value.class}</td>
</tr>
<tr>
<th width="50">Beds</th>
<td id="beds">${value.beds}</td>
</tr>
<tr>
<th width="50">Owner</th>
<td id="owner">${value.owner}</td>
</tr>
<tr>
<th width="50">Province</th>
<td id="province">${value.province}</td>
</tr>
<tr>
<th width="50">City</th>
<td id="city">${value.city}</td>
</tr>
<tr>
<th width="50">Address</th>
<td id="address">${value.address}</td>
</tr>
`;
$('#body')append(element);
});
In your below code, you are appending value by the fieldId, that's why it is only appending only the last row(each iteration, the value is being updated in background) values are being set.
$('#code').html(value.code);
$('#name').html(value.name);
$('#type').html(value.type);
$('#class').html(value.class);
$('#beds').html(value.beds);
$('#owner').html(value.owner);
$('#province').html(value.province);
$('#city').html(value.city);
$('#address').html(value.address);
So, to achieve your purpose, you have to append these as a complete row and insert into the table, not just appending fieldwise value but rowwise and insert that row into the table. I hope you get my point.
The problem is that you are always changing the same elements of the same table. I think you will need to append one table per row:
$.each(data.data, function(key, value) {
$(".result").append('<table class="mb-3 table table-bordered table-hover">...</table>')
});
However, you may want to use Handlebars or some other templating library to avoid creating a long string with the table.

javascript get/store data from table

I'm trying to catch the data based on the id's after clicking the button (like store them) in order to use it for inserting needed id's afterwards into the DB. The js written is not working as expected, any ideas what is missing? Thank you for the support.
<script>
function goo() {
idprod=$("#idprod").val();
nprod=$("#nprod").val();
lastprod=$("#lastprod").val();
solarprod=$("#solarprod").val();
locprod=$("#locprod").val()
}
</script>
<form name="goo" method="post">
<table border="1">
<tr>
<th>ID</th>
<th>Name</th>
<th>Lastname</th>
<th>WK_Solar</th>
<th>Location</th>
<th>Save</th>
</tr>
<tr>
<td id="idprod">P1</td>
<td id="nprod">James</td>
<td id="lastprod">Lee</td>
<td id="solarprod">$1555</td>
<td id="locprod">Queens</td>
<td><input type="hidden" name="active" value="active"><input type="submit" name="submit" value="goo"></td>
</tr>
<tr>
<td id="idprod">P2</td>
<td id="nprod">Marc</td>
<td id="lastprod">Hoobs</td>
<td id="solarprod">$955</td>
<td id="locprod">Bronx</td>
<td><input type="hidden" name="active" value="active"><input type="submit" name="submit" value="goo"></td>
</tr>
</table>
</form>
1- You are using val which is the attr Value. you should use html() or text() to get the value.
2- You have two rows, you should browse those two rows and get the data from each row
function goo() {
var firstRow = $(".test tbody tr").last();
idprod=firstRow.find("#idprod").html();
nprod=firstRow.find("#nprod").html();
lastprod=firstRow.find("#lastprod").html();
solarprod=firstRow.find("#solarprod").html();
locprod=firstRow.find("#locprod").html()
console.log(idprod)
}
$(document).ready(function(){
goo();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="goo" method="post">
<table border="1" class="test">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Lastname</th>
<th>WK_Solar</th>
<th>Location</th>
<th>Save</th>
</tr>
</thead>
<tr>
<td id="idprod">P1</td>
<td id="nprod">James</td>
<td id="lastprod">Lee</td>
<td id="solarprod">$1555</td>
<td id="locprod">Queens</td>
<td><input type="hidden" name="active" value="active"><input type="submit" name="submit" value="goo"></td>
</tr>
<tr>
<td id="idprod">P2</td>
<td id="nprod">Marc</td>
<td id="lastprod">Hoobs</td>
<td id="solarprod">$955</td>
<td id="locprod">Bronx</td>
<td><input type="hidden" name="active" value="active"><input type="submit" name="submit" value="goo"></td>
</tr>
</table>
</form>

How to add delete button after new row opened using Angular.js?

I need to add a delete (minus) button after adding a new row using plus button. I am providing my code below.
<table class="table table-bordered table-striped table-hover" id="dataTable" >
<thead>
<tr>
<th>Day</th>
<th>Category</th>
<th>Sub Subcategory</th>
<th>Comments Or special promotion</th>
<th>Add More</th>
</tr>
</thead>
<tbody id="detailsstockid">
<tr ng-repeat="d in days">
<td>{{d.day_name}}</td>
<td>
<table class="table table-bordered table-striped table-hover">
<tbody>
<tr ng-repeat="answer in d.answers">
<td>
<select class="form-control" id="answer_{{$index}}_category" name="answer_{{$index}}_category" ng-model="answer.catagory" ng-options="cat.name for cat in listOfCatagory track by cat.value">
<option value="">Select Category</option>
</select>
</td>
</tr>
</tbody>
</table>
</td>
<td>
<table class="table table-bordered table-striped table-hover">
<tbody>
<tr ng-repeat="answer in d.answers">
<td>
<select class="form-control" id="answer_{{$index}}_subcategory" name="answer_{{$index}}_subcategory" ng-model="answer.subcatagory" ng-options="sub.name for sub in listOfSubCatagory[$parent.$index] track by sub.value">
<option value="">Select Subcategory</option>
</select>
</td>
</tr>
</tbody>
</table>
</td>
<td>
<table class="table table-bordered table-striped table-hover">
<tbody>
<tr ng-repeat="answer in d.answers">
<td>
<input type="text" id="answer_{{$index}}_comment" name="answer_{{$index}}_comment" placeholder="Add Comment" ng-model="answers.comment" class="form-control oditek-form">
</td>
</tr>
</tbody>
</table>
</td>
<td>
<input type="submit" name="plus" id="plus" value="+" style="width:20px; text-align:center;" ng-click="addNewRow(d.answers)">
</td>
</tr>
</tbody>
</table>
controller file is given below.
$scope.days=[];
$http({
method:'GET',
url:"php/customerInfo.php?action=day",
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(function successCallback(response){
//console.log('day',response.data);
angular.forEach(response.data,function(obj){
obj.answers = [];
$scope.addNewRow(obj.answers);
$scope.days.push(obj);
})
},function errorCallback(response) {
})
$scope.addNewRow = function(answers) {
answers.push({
category: null,
subcategory: null,
comment: null
});
};
Here I have one plus button when user is clicking on it a new row is adding. I need when a new row will add one delete (minus) button will create for previous one and plus button will remain with new one. When user will click on minus button the corresponding row will be deleted.
In your HTML file:
<button ng-click="removeRow($index)">
In your angular controller code:
$scope.removeRow = function(id) {
angular.forEach(answers, function(currentAnswer, index) {
if (currentAnswer.id === id) {
answers.splice(index, 1);
}
});
}
Note that answers needs to be accessible for this to work.
add html for remove button beside plus button like below:
<button type="button" ng-click="removeNewRow($index)" ng-show="$first && !$last">
and add a function in controller:
$scope.removeNewRow= function(index) {
$scope.d.answers.splice(index, 1);
}

use button to pass td data

I have a table that I want to give the user the ability to select. I added an button, value="Update", to the beginning of the row, and assigned an onclick value. My problem is that I want to send other items(in td>s on the same row) from the row to the function called by the button.
How do I get the information from the row the button is on? I would like to pass the "Name" and "Last Update Time" to the function the button calls. I tried using the following:
$("#Report input[name=btn_id]").closest('td').attr('text')
but it returns "undefined," which I am not surprised by, as I think this is due to it not knowing what row of the table to pull from.
Here is a view of the table:
Here is the code behind the table:
<table align="center" border="1" class="report" id="report">
<thead>
<tr>
<th width="75">Update</th>
<th width="500">Name</th>
<th width="50">Info</th>
<th width="100">location</th>
<th width="100">Last Update Time</th>
</tr>
</thead>
<tbody>
<tr class="parent" id="other_app">
<td align="center">
<input type="button" name="btn_id" value="Update" onclick="UpdateRec(d1)">
</td>
<td name="App_Name">Test1</td>
<td align="center">None</td>
<td align="center">Desktop</td>
<td align="center">2014-06-30 18:22:39</td>
</tr>
<tr class="parent" id="other_app">
<td align="center">
<input type="button" name="btn_id" value="Update" onclick="UpdateAppRec(d1)">
</td>
<td name="App_Name">Test1</td>
<td align="center">None</td>
<td align="center">Server</td>
<td align="center">2014-03-30 16:20:15</td>
</tr>
</tbody>
Any help would be appreciated.
Embrace the power of this.
Using:
onclick="UpdateRec(this)"
..in your function:
function UpdateRec(el) {
var targetRow = $(el).parents('tr')
...
}
Using this passes a reference to the clicked element. You can then use jQuery to select the parent table row. From there you can use .find() to select anything in that row.
Another way to do this would be to use HTML5 data- attributes on this button itself:
<input type="button" name="btn_id" value="Update" onclick="UpdateRec(d1)" data-appName="something" />
In the same function you can then use $(el).data('appName') to get the value directly without looking up values in other DOM elements.
//Add a click listener on all your buttons using event delegation
$('#Report').click(onUpdateButtonClicked, 'input[name=btn_id]');
function onUpdateButtonClicked() {
var rowValues = $(this)
.parent() //select parent td
.nextAll() //select all next siblings of that parent td
.map(function () { //loop through the tds, collecting their text value
return $(this).text();
}).get(); //return the result as an array
//do what you want with rowValues
}
I would suggest you to use common class for all update buttons with common click event handler.
Here is the fiddle: http://jsfiddle.net/jwet6z6x/
HTML:
<table align="center" border="1" class="report" id="report">
<thead>
<tr>
<th width="75">Update</th>
<th width="500">Name</th>
<th width="50">Info</th>
<th width="100">location</th>
<th width="100">Last Update Time</th>
</tr>
</thead>
<tbody>
<tr class="parent" id="other_app">
<td align="center">
<input class="updateBtn" type="button" name="btn_id" value="Update">
</td>
<td name="App_Name">Test1</td>
<td align="center">None</td>
<td align="center">Desktop</td>
<td align="center">2014-06-30 18:22:39</td>
</tr>
<tr class="parent" id="other_app">
<td align="center">
<input class="updateBtn" type="button" name="btn_id" value="Update">
</td>
<td name="App_Name">Test1</td>
<td align="center">None</td>
<td align="center">Server</td>
<td align="center">2014-03-30 16:20:15</td>
</tr>
</tbody>
Javascript:
$(".updateBtn").click(function(){
var name = $(this).parent().parent().find('td').eq(1).html()
var time = $(this).parent().parent().find('td').eq(4).html()
alert (name);
alert (time);
})
I would do as follow : http://jsfiddle.net/Lk91cpup/2/
<table>
<tr id="row_1">
<td>
<input type="button" id="btn_row_1" class="btn" value="Update">
</td>
<td id="text_row_1">Test1</td>
<td>None</td>
<td>Desktop</td>
<td >2014-06-30 18:22:39</td>
</tr>
<tr id="row_2">
<td>
<input type="button" id="btn_row_2" class="btn" value="Update">
</td>
<td id="text_row_2">Test2</td>
<td>None</td>
<td>Server</td>
<td>2014-03-30 16:20:15</td>
</tr>
</table>
And Javascript
$(document).ready(function(){
$(".btn").click(function(){
var id = this.id.substring(this.id.lastIndexOf("_") + 1);
alert($("#text_row_" + id).text());
});
});
<tr class="parent" id="other_app">
<td align="center">
<input type="button" name="btn_id" value="Update" onclick="UpdateRec(d1, 'Test1', 'None', 'Desktop', '2014-06-30')">
</td>
<td name="App_Name">Test1</td>
<td align="center">None</td>
<td align="center">Desktop</td>
<td align="center">2014-06-30 18:22:39</td>
</tr>
Since you have already written a javascript function call why not just include the things you need right?
This is simplier but not the best practise.

Categories

Resources