I am a bit stuck when creating the PDF from the html template. if i use the static entries it does work but i am looking to generate the pdf for multiple items and the items can vary each time, i am not sure if i am missing something any suggestion guys please.
after i added .map function in the pdfTemplate.js file as below to go through each object and get the price, it seems to not working properly
snippet from the main ./documents/pdfTemplate Js file
customer_dataand_Itemsbought.map((eachitem) => {
total = total + eachitem.price;
return ` <tr class="heading">
<td>Bought items:</td>
<td>Price</td>
</tr>
<tr class="item">
<td>First item:</td>
<td>${eachitem.price}$</td>
</tr>
<tr class="item">
<td>Second item:</td>
<td>${eachitem.price}$</td>
</tr>`;
})`
Note: PDF is still generating but missing every bit that i included after the .map function
main ./documents/pdfTemplateJs file
module.exports = (customer_dataand_Itemsbought) => {
//customer_dataand_Itemsbought is array of objects[obj[0],obj[1],...] and at obj[0] is the customer details object and after that each index object contains the customer bought items detail/price
let customer_Name = customer_dataand_Itemsbought[0].user_FirstName;
let receipt_Id = customer_dataand_Itemsbought[0].Invoice_No_latest;
let total_Price;
customer_dataand_Itemsbought.shift();
const today = new Date();
return `
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>PDF Result Template</title>
<style>
........
</style>
</head>
<body>
<div class="invoice-box">
<table cellpadding="0" cellspacing="0">
<tr class="top">
<td colspan="2">
<table>
<tr>
<td class="title"><img src="https://i2.wp.com/cleverlogos.co/wp-content/uploads/2018/05/reciepthound_1.jpg?fit=800%2C600&ssl=1"
style="width:100%; max-width:156px;"></td>
<td>
Datum: ${`${today.getDate()}. ${today.getMonth() + 1}. ${today.getFullYear()}.`}
</td>
</tr>
</table>
</td>
</tr>
<tr class="information">
<td colspan="2">
<table>
<tr>
<td>
Customer name: ${customer_Name} // this still appears on the PDF
</td>
<td>
Receipt number: ${receipt_Id} // this still appears on the PDF
</td>
</tr>
</table>
</td>
</tr>`;
// here i used the .map function to go through each array object. nothing appears from here onwards on the pdf
customer_dataand_Itemsbought.map((eachitem) => {
total = total + eachitem.price;
return ` <tr class="heading">
<td>Bought items:</td>
<td>Price</td>
</tr>
<tr class="item">
<td>First item:</td>
<td>${eachitem.price}$</td>
</tr>
<tr class="item">
<td>Second item:</td>
<td>${eachitem.price}$</td>
</tr>`;
})`
</table>
<br />
<h1 class="justify-center">Total price: ${total_Price}£</h1>
</div>
</body>
</html>
`;
};
at server.js side
const pdf = require("html-pdf");
const pdfTemplate = require("./documents/pdfTemplate");
pdf.create(pdfTemplate(customer_dataand_Itemsbought), {}).toFile("./filename.pdf", function (err, res) {
if (err) {
console.log(err);
}
});
When you have enclosed map function's body in curly braces - meaning you have multiple statements for processing data, you are expected to return from it explicitly:
customer_dataand_Itemsbought.map((eachitem) => {
total = total + eachitem.price;
return `<tr class="heading">
<td>Bought items:</td>
<td>Price</td>
</tr>
<tr class="item">
<td>First item:</td>
<td>${eachitem.price}$</td>
</tr>
<tr class="item">
<td>Second item:</td>
<td>${eachitem.price}$</td>
</tr>`;
})
Related
I have an excel spreadsheet template. I need to create excel file from data in html/php page. That is, the data on the html page is scattered throughout the page, and I need to somehow collect all this data (through classes or ids) and place it in certain cells of the table.
I tried a lot of ready-made solutions, for example https://github.com/jmaister/excellentexport/tree/master/test
<html>
<head>
<script type="text/javascript" src="https://unpkg.com/xlsx#0.15.1/dist/xlsx.full.min.js"></script>
</head>
<body>
<table id="tbl_exporttable_to_xls" border="1">
<thead>
<th>Sr</th>
<th>Name</th>
<th>Location</th>
<th>Job Profile</th>
</thead>
<tbody>
<tr>
<td>1</td>
<td>
<p>Amit Sarna</p>
</td>
<td>Florida</td>
<td>Data Scientist</td>
</tr>
<tr>
<td>2</td>
<td>
<p>Sagar Gada</p>
</td>
<td>California</td>
<td>Sr FullStack Dev</td>
</tr>
<tr>
<td>3</td>
<td>
<p>Ricky Marck</p>
</td>
<td>Nevada</td>
<td>Sr .Net Dev</td>
</tr>
<tr>
<td>4</td>
<td>
<p>Andrea Ely</p>
</td>
<td>New York</td>
<td>Sr Delivery Mgr</td>
</tr>
<tr>
<td>5</td>
<td>
<p>Sunita Devgan</p>
</td>
<td>Colorado</td>
<td>UiUx Expert</td>
</tr>
</tbody>
</table>
<button onclick="ExportToExcel('xlsx')">Export table to excel</button>
<script>
function ExportToExcel(type, fn, dl) {
var elt = document.getElementById('tbl_exporttable_to_xls');
var wb = XLSX.utils.table_to_book(elt, { sheet: "sheet1" });
return dl ?
XLSX.write(wb, { bookType: type, bookSST: true, type: 'base64' }) :
XLSX.writeFile(wb, fn || ('MySheetName.' + (type || 'xlsx')));
}
</script>
</body>
</html>
Only import from html table is used everywhere.
Sorry for my English, so I'm attaching images for more details.
enter image description here
Tried options
https://codepedia.info/javascript-export-html-table-data-to-excel
https://github.com/jmaister/excellentexport/tree/master/test
https://www.webslesson.info/2021/07/how-to-display-excel-data-in-html-table.html
https://codepedia.info/javascript-export-html-table-data-to-excel
but everywhere there is an import only by html table
I have a script that fetches the data from a link and then inserts that in tables and shows it to the user. the script worked fine. but then I decided to make the function more dynamic so I added 2 arguments name and Html div name where the data will display. it worked fine when I called the function the first time but it doesn't show any data on the second call. I'm using PHP for my projects and new to javascript. but I made a similar function in PHP but that works. any suggestions?
function getInfoByCountry(name, displayName) {
fetch("https://something.com/countries/" + name)
.then(res => res.json())
.then(data => {
output = `
<tr>
<td>Total Cases</td>
<td>${data.cases}</td>
</tr>
<tr>
<td>Today Cases</td>
<td>${data.todayCases}</td>
</tr>
<tr>
<td>Deaths</td>
<td>${data.deaths}</td>
</tr>
<tr>
<td>Recovered</td>
<td>${data.recovered}</td>
</tr>
<tr>
<td>Critical</td>
<td>${data.critical}</td>
</tr>
<tr>
<td>Active Cases</td>
<td>${data.active}</td>
</tr>
`;
document.getElementById(displayName).innerHTML = output;
});
}
getInfoByCountry("USA", "USAInfo");
getInfoByCountry("China", "ChinaInfo");
<div class="table-responsive">
<table class="table table-striped mb-0">
<tbody id="ChinaInfo">
</tbody>
</table>
</div>
Add return like this
function getInfoByCountry(name, displayName) {
var display = document.getElementById(displayName);
return fetch("https://smthing.com/countries/"+name)
.then(res => res.json())
.then(data => {
output = `
<tr>
<td>Total Cases</td>
<td>${data.cases}</td>
</tr>
<tr>
<td>Today Cases</td>
<td>${data.todayCases}</td>
</tr>
<tr>
<td>Deaths</td>
<td>${data.deaths}</td>
</tr>
<tr>
<td>Recovered</td>
<td>${data.recovered}</td>
</tr>
<tr>
<td>Critical</td>
<td>${data.critical}</td>
</tr>
<tr>
<td>Active Cases</td>
<td>${data.active}</td>
</tr>
`;
document.getElementById(displayName).innerHTML += output;
}
);
}
getInfoByCountry("USA", "display");
getInfoByCountry("China", "display");
you just need to add return statement for returning output.
here is fiddle you can check function.
function getInfoByCountry(name,displayName) {
debugger;
return fetch("https://jsonplaceholder.typicode.com/posts/"+name)
.then(res => res.json())
.then(data => {
output = `
<tr>
<td>Total Cases</td>
<td>${data.title}</td>
</tr>
<tr>
<td>Today Cases</td>
<td>${data.body}</td>
</tr>
`;
document.getElementById(displayName).innerHTML = output;
});
}
You are adding the result using displayName as id attribute, you should add another one for USAinfo as mentioned in the comments, or a better implementation would be to create the table dynamically and append the result to the container.
function getInfoByCountry(name, displayName) {
fetch("API_URL" + name)
.then(res => res.json())
.then(data => {
output = `
<table class="table table-striped mb-0">
<tbody>
<tr>
<td>Total Cases</td>
<td>${data.cases}</td>
</tr>
<tr>
<td>Today Cases</td>
<td>${data.todayCases}</td>
</tr>
<tr>
<td>Deaths</td>
<td>${data.deaths}</td>
</tr>
<tr>
<td>Recovered</td>
<td>${data.recovered}</td>
</tr>
<tr>
<td>Critical</td>
<td>${data.critical}</td>
</tr>
<tr>
<td>Active Cases</td>
<td>${data.active}</td>
</tr>
</tbody>
</table><hr />
`;
document.getElementById("container").innerHTML += output;
});
}
getInfoByCountry("USA", "USAInfo");
getInfoByCountry("China", "ChinaInfo");
table, td {
border: 1px solid;
}
<div id="container" class="table-responsive">
</div>
Every time the toggle is clicked, all payments are getting replaced with new payments. My problem is how to maintain the payments of a particular index of every click and show at respective index. please help me out
here is my html
<tbody data-ng-repeat="invoice in relatedInvoices>
<tr>
<td class="td-bottom-border">
{{invoice.PayableCurrencyCode}} {{invoice.PayablePaidAmount | number: 2}}<br />
<small>
<a data-ng-click="isOpenPayablePayments[$index] = !isOpenPayablePayments[$index]; togglePayablePayments(invoice.PayableInvoiceId)">Paid</a>
</small>
</td>
</tr>
<tr data-ng-show="isOpenPayablePayments[$index]">
<td>
<table>
<thead>
<tr>
<th>Transaction Id</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="payment in payablePayments">
<td>{{payment.TransactionId}}</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
Here is my javascript
var getPayments = function (invoiceId) {
paymentService.getPayments(invoiceId).then(function (paymentsResponse) {
return paymentsResponse.data;
});
};
$scope.togglePayablePayments = function(invoiceId) {
$scope.payablePayments = getPayments(invoiceId);
};
If I understood correctly, you want to have "payablePayments" for every invoice.
This is working: http://plnkr.co/edit/cj3jxZ?p=info
Try something like
// init at beginning
$scope.payablePayments = [];
$scope.togglePayablePayments = function(invoiceId) {
$scope.payablePayments[invoiceId] = getPayments(invoiceId);
};
and then
<tr data-ng-repeat="payment in payablePayments[invoice.PayableInvoiceId]">
Otherwise you overwrite the object for the preceding invoice.
I want to have an iterative moving over an array of users , and fill every td with a unique user in array, but I dont want to repeat and produce new html code in every ng-repeat's step.
I just want have a moving on the td's and for each one , put a user inside that td.
<!DOCTYPE html>
<html ng-app="fill">
<head>
<?php include "includes/head.php" ?>
<script type="text/javascript">
(function(){
var fill=angular.module("fill",[]);
fill.controller("fillTable",function($scope){
$scope.users=[ {name:"jack"},
{name:"joe"},
{name:"alen"},
{name:"mina"},
{name:"mari"},
{name:"karen"}
];
});
})()
</script>
</head>
<body>
<table ng-controller="fillTable" border=1>
<tbody ng-repeat="user in users">
<tr>
<td>user 1:{{user.name}}</td>
<td>user 2:{{user.name}}</td>
</tr>
<tr>
<td>user 3:{{user.name}}</td>
<td>user 4:{{user.name}}</td>
</tr>
<tr>
<td>user 5:{{user.name}}</td>
<td>user 6:{{user.name}}</td>
</tr>
</tbody>
</table>
</body>
</html>
actually, i have a grid with four columns that i created it by semantic-ui-grid.
now i want to read many articles from dataBase's tables then i have puting that datas inside grid's columns.{like a 'pinterest style' page } a pic for more explain , please see it
You can create pairs in controller:
$scope.users = [
{name:"jack"},
{name:"joe"},
{name:"alen"},
{name:"mina"},
{name:"mari"},
{name:"karen"}
];
$scope.pairs = [];
for (var i = 0; i < $scope.users.length; i+=2) {
$scope.users[i].index = i+1;
if ($scope.users[i+1]) {
$scope.users[i+1].index = i+2;
$scope.pairs.push([$scope.users[i], $scope.users[i+1]]);
} else {
$scope.pairs.push([$scope.users[i]]);
}
}
and iterate over pairs:
<table ng-controller="fillTable" border=1>
<tbody>
<tr ng-repeat="pair in pairs">
<td ng-repeat="user in pair">user {{user.index}}:{{user.name}}</td>
</tr>
</tbody>
</table>
There is no other workaround than to make a special array containing user pairs :
$scope.$watch('users', function() {
$scope.userPairs = [];
for (var i=0;i<$scope.users.length;i=i+2) {
$scope.userPairs.push({
name1 : $scope.users[i].name,
name2 : $scope.users[i+1].name
})
}
})
also use ng-repeat properly (you want to iterate over <tr>'s not <tbody>'s :
<table border=1>
<tbody>
<tr ng-repeat="user in userPairs">
<td>user 1:{{user.name1 }}</td>
<td>user 2:{{user.name2 }}</td>
</tr>
</tbody>
</table>
demo -> http://plnkr.co/edit/yK3F9US4XuS6sPnVv0Dd?p=preview
<table ng-controller="fillTable" border=1>
<tbody ng-repeat="user in users track by $index">
<tr>
<td>user 1:{{users[$index].name}}</td>
<td>user 2:{{users[$index+1].name}}</td>
</tr>
<tr>
<td>user 3:{{users[$index+2].name}}</td>
<td>user 4:{{users[$index+3].name}}</td>
</tr>
<tr>
<td>user 5:{{users[$index+4].name}}</td>
<td>user 6:{{users[$index+5].name}}</td>
</tr>
</tbody>
</table>
Trying to take this table and take the names, when I click one radio button it changes the names from something like: Tom Hanks to Hanks, Tom. Here is the html:
<h1>Address Book</h1>
Show Names as:
<input name="change_last_first" value="last" type="radio">First, Last
<input name="change_last_first" value="first" type="radio">Last, First
<div>
<table <thead="">
<tbody>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
</tr>
</tbod
<tbody>
<tr>
<td>9001</td>
<td class="name">Tom Hanks</td>
<td>tomhanks#moviestars.com</td>
</tr>
<tr>
<td>9002</td>
<td class="name">Bruce Willis</td>
<td>brucewillis#moviestars.com</td>
</tr>
<tr>
<td>9003</td>
<td class="name">Jim Carrey</td>
<td>jimcarrey#moviestars.com</td>
</tr>
<tr>
<td>9004</td>
<td class="name">Tom Cruise</td>
<td>tomcruise#moviestars.com</td>
</tr>
<script>
</script>
</tbody>
</table>
</div>
<meta charset="utf-8">
<title>Interview Test</title>
<link rel="stylesheet" href="./webassets/style.css" media="screen" type="text/css">
<h1>Company Staff List</h1>
<div>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>9001</td>
<td>Tom Hanks</td>
</tr>
<tr>
<td>9002</td>
<td>Bruce Willis</td>
</tr>
<tr>
<td>9003</td>
<td>Jim Carrey</td>
</tr>
<tr>
<td>9004</td>
<td>Tom Cruise</td>
</tr>
</tbody>
</table>
</div>
Here is the jquery, its all I could come up with and does not work at all. :(
$(document).ready(function () {
$("input[name='change_last_first']").click(function () {
$(".name").text(function() {
$(this).split(" ").reverse();
});
});
});
});
You need to return the result. Also since you are using the function arg syntax of text use the second argument of the function for the current text.
$(".name").text(function(_, cur) {
return curText.split(/\s+|,/).reverse();
});
Fiddle
Another easy way to handle this assuming the general format of name is First Last or Last, First:
$("input[name='change_last_first']").change(function () {
var arr = [" ", ","],
sep = this.value === 'first' ? 0 : 1;
$(".name").text(function (_, curText) {
return curText.split(arr[sep % 2]).reverse().join(arr[(sep + 1) % 2]);
});
});
Demo
For this you need to split full name with space and than you can use reverse().
Note: because reverse() is a method of array instances. It won't directly work on a string. You should first split the characters of the string into an array, reverse the array and then join back into a string.
$("input[name='change_last_first']").click(function () {
$(".name").each(function() {
var revName = $(this).text().split(" ").reverse().join(" ");
$(this).text(revName);
});
});
Try This