dompdf with special characters - laravel-5

I have following code:
$pdf = \App::make('dompdf');
$pdf->loadView('offers.pdf',compact('email','messages'));
return $pdf->stream();
pdf.blade.php:
<!doctype html>
<html class="no-js" lang="sk">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<style type="text/css">
* {
font-family: "Arial";
}
</style>
</head>
<body>
Rozpočet, Voliteľné časti
</body>
</html>
PDF document looks like:
Rozpo?et,Volite?né ?asti
But I need show special characters like in pdf.blade.php file, do you have some solutions for me?

This worked for me:
<html>
<head>
<meta http-equiv="Content-Type" content="charset=utf-8" />
<style type="text/css">
* {
font-family: "DejaVu Sans Mono", monospace;
}
</style>
</head>
<body>your content ćčžšđ...</body>
</html>

For Laravel 8, I solved my problem with the help of the https://github.com/mpdf/mpdf PHP package.
First of all, I've created a view template in my resources folder,
"pdfview.blade.php"
<!DOCTYPE HTML>
<html lang="fa">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<table dir="rtl">
<tr>
<th>ردیف</th>
<th>عنوان</th>
<th>توضیحات</th>
</tr>
#foreach ($items as $key => $item)
<tr style="padding: 5px">
<td style="padding: 10px">{{ ++$key }}</td>
<td style="background: #efefef; padding: 10px">{{ $item->title }}</td>
<td style="padding: 10px">{{ $item->body }}</td>
</tr>
#endforeach
</table>
</body>
and created a method in my controller:
public function pdfview()
{
$items = Post::get();
// change the root directory of fonts.
$fontDirs = public_path() . "/fonts/MY_FONT_NAME/";
// specify the font
$fontData = [
"MY_FONT_NAME" => [
'R' => 'MY_FONT_NAME.ttf'
],
];
$mpdf = new Mpdf([
'fontDir' => $fontDirs,
'fontdata' => $fontData,
'default_font' => 'MY_FONT_NAME'
]);
// render view as HTML
$html = view('pdfview', compact('items'))->render();
$mpdf->WriteHTML($html);
return $mpdf->Output();
}

Related

Why is the string not added to the property via Model.addObject?

I created #ControllerAdvice to handle BindException:
#ControllerAdvice
class globalControllerAdvice {
#ExceptionHandler(BindException.class)
public ModelAndView handleMyException(HttpServletRequest req, Exception e) {
ModelAndView model = new ModelAndView();
model.addObject("myerror",e.getErrCode());
model.addObject("message",e.getMessage());
model.addObject("exception","bind exception");
model.setViewName("error");
return model;
}
}
And created error.html :
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Handing Form Submission</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style>
table td{
vertical-align:top;
border:solid 1px #888;
padding:10px;
}
</style>
</head>
<body>
<h1>Error Page</h1>
<table>
<tr>
<td>Error</td>
<td th:text="${myerror}"/>
</tr>
<tr>
<td>Message</td>
<td th:text="${message}"/>
</tr>
<tr>
<td>Exception</td>
<td th:text="${exception}"/>
</tr>
</table>
</body>
</html>
And when executing, when I make a mistake on purpose, the page appears normally,but the properties are not filled in .That is, a table is created, but the text "${myerror}" , "${message}" , "${exception}" are not filled in with e.getErrCode() , e.getMessage() ,
"bind exception". Can anyone tell me what the problem is? thanks

Thymeleaf can't see For-each variable

Here is my Service ( It just gets a list of entities )
#Service
public class ProcedureService {
#Autowired
ProcedureRepository procedureRepository;
public List getProceduresList() {
List<Procedure> procedureList;
procedureList = procedureRepository.findAll();
return procedureList;
}
}
Here is my Controller. It just puts list he gets to view.
#Controller
public class ServicesController {
#Autowired
ProcedureService procedureService;
#GetMapping("/services")
public String getCustomer(Model model) {
List<Procedure> procedures = procedureService.getProceduresList();
model.addAttribute("procedures", procedures);
return "services";
}
}
And here is my real problem. Thyme leaf just doesn't see the entity in a List ( it sees the list though ). Here is my screen and full code of View
<!DOCTYPE html>
<html lang="en">
<head>
<title>SpringMVC + Thymeleaf + Bootstrap 4 Table Example</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h1>Customer Table</h1>
<div class="row col-md-7 table-responsive">
<table id="customerTable" class="table">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Age</th>
<th>Street</th>
<th>Postcode</th>
</tr>
</thead>
<tbody>
<tr th:each="procedure: ${procedures}">
<td th:text="${procedure.}" />
<td th:text="${procedure.getId}" />
</tr>
</tr>
</tbody>
</table>
</div>
</div>
I forgot about html lang="en" xmlns:th="http://www.thymeleaf.org" in html so th wasn't really working.

Laravel barryvdh/laravel-dompdf multiple components of view in one pdf

I am using barryvdh/laravel-dompdf to generate pdf.
I'm trying generate one pdf file with multiple pages from data collection the problem is that I get only first element and one page. Using foreach loop to generate pages. Also I was trying to use foreach in my blade, but then I get only the last page.
Controller:
public function multiplePagesPdf(Request $request)
{
$kuponai = Kuponas::all();
//dd($kuponas);
$html = '';
foreach($kuponai as $kuponas)
{
$view = view('pdf.multiple')->with(compact('kuponas'));
$html .= $view->render();
}
$pdf = PDF::loadHTML($html);
$sheet = $pdf->setPaper('a4', 'landscape');
return $sheet->stream('sugeneruoti.pdf');
}
Maybe problem in my blade file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Dovanų kuponas</title>
</head>
<body>
<div class="coupon">
<div class="page">
<div class="subpage">
<div class="container" style="
width: 21cm;
height: 16cm;
position: absolute;
top: 6.8cm;
font-family: DejaVu Sans;
background: white;
">
<h2>{{!! $kuponas->kupono_nr !!}}</h2>
<h3 style="margin-left: 3.2cm">
Dovanų kupono numeris:
<span style="color: black"></span>
</h3>
</div>
</div>
</div>
</div>
</body>
</html>
<style>
#page {
size: A4;
margin: 0;
}
#media print {
.page {
margin: 0;
border: initial;
border-radius: initial;
width: initial;
min-height: initial;
box-shadow: initial;
background: initial;
page-break-after: always;
}
}
</style>
There are certain things that are wrong in the code snippet you have provided, I will explain those first then provide correct way of doing it(for which I get results).
Firstly
you have used with & compact together, I don't know if it gets correct results but you should use any one of them or use array syntax of view method.
Secondly
what you are doing it you are rendering the view to html & then concating it, so , your html would look like,
<html>
.... content
</html>
<html>
.... content
</html>
& so on.
Thirdly
You css is messed up & not working as you want because of inline css you have added.
Solution
I would have used View Components to create similar views with different data.
So we would create a component in resources/views/components/single.blade.php (here I have named it single).
I have added your repeative code in the component single from your view. Now your coupon div class is in the component single.
<div class="coupon">
<div class="page">
<div class="subpage">
<div>
<h2>{{ $kuponas->kupono_nr }}</h2>
<h3>
Dovanų kupono numeris:
<span></span>
</h3>
</div>
</div>
</div>
</div>
Then in your view,
<!DOCTYPE html>
<html lang="en">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<head>
<title>Dovanų kuponas</title>
<style>
.page-break {
page-break-after: always;
}
</style>
</head>
<body>
#php $count = 0;#endphp
#foreach ($kuponai as $kuponas)
#php $count++ #endphp
<div class="container {{ (count($kuponai)-1 >= $count) ? 'page-break' : '' }}">
#component('pdf.components.single', ['kuponas' => $kuponas])
#endcomponent
</div>
#endforeach
</body>
</html>
use page-break class to create breaks, I have used count condition to remove one extra page break. I am passing the data of kuponas to the component.
Finally change your controller,
public function multiplePagesPdf(Request $request)
{
$kuponai = Kuponas::all();
//dd($kuponas);
$view = view('pdf.multiple', ['kuponai' => $kuponai]);
$html = $view->render();
$pdf = PDF::loadHTML($html)->setPaper('a4', 'landscape');
return $pdf->stream('sugeneruoti.pdf');
}

How to Send image using org.apache.velocity.VelocityContext for email

MimeMessagePreparator mimeMessagePreparator=new MimeMessagePreparator() {
#Override
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper mimeMessageHelper=new MimeMessageHelper(mimeMessage);
mimeMessageHelper.setTo(requestQuotationPojo.getEmailId().toString());
mimeMessageHelper.setFrom("vikasglobaljapan#gmail.com");
mimeMessageHelper.setText("Your Request Quotation Number"+requestQuotationPojo.getRfqId());
mimeMessageHelper.setSubject("Request Quotation Details");
VelocityContext velocityContext = new VelocityContext();
requestQuotationPojo.setImage(new StringBuffer(application_url.concat(requestQuotationPojo.getImage().toString())));
requestQuotationPojo.setRfqId(new StringBuffer(rfqId));
velocityContext.put("image", requestQuotationPojo.getImage());
velocityContext.put("rfqDetails", requestQuotationPojo);
velocityContext.put("image",application_url.concat(requestQuotationPojo.getImage().toString()));
StringWriter stringWriter = new StringWriter();
velocityEngine.mergeTemplate("com/gjcp/dao/daoImpl/customer/templateName.vm", "UTF-8", velocityContext, stringWriter);
mimeMessageHelper.setText(stringWriter.toString(), true);
}
template.vm
<!doctype html>
<html lang="en">
<head>
<style>
table, th, td {
border: 1px solid black;
}
</style>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>Document</title>
</head>
<body>
<table style="width:100%">
  <tr>
    <th>Product Name</th>
    <th>Quote Number</th>
    <th>Image</th>
<th>Quantity</th>
  </tr>
<tr>
<td>${rfqDetails.productName}</td>
<td> ${rfqDetails.rfqId}</td>
<td><img src="${rfqDetails.image}" border="0" width="50" height="50"></td>
<td>${rfqDetails.quantity}</td>
</tr>
</table>
</body>
</html>
I suppose that your image is a byte array. So you should add image to velocity context as base64 string.
velocityContext.put("image", Base64.encode(requestQuotationPojo.getImage()));
And use this img tag in your template file.
<img src="data:image/jpg;base64,${image}" border="0" width="50" height="50"/>
${websitename} : Write Your website name.
${rfqDetails.image} : your image path.
Like Your image url: http://test.com/folder/abc.png
#set($imgsrc="http://${websitename}/${rfqDetails.image})
<img width="50" src="$imgsrc" border="0" height="50" alt="test">

Correct way to initialize kendo widgets inside template

Im inserting an widget within template like this:
<script id="example-template" type="text/x-kendo-template">
<div data-role="collapsible" data-expand="expandHandler">
<h3>#= example #</h3>
</div>
</script>
But the widget is does not initialize, just show as plain html.
Some people suggest to use kendo.mobile.init and it works, but looks like a hack. This method is not at least documented.
My question is: what can I do to properly initialize widgets inside template?
Complete example:
<!DOCTYPE html>
<html>
<head>
<link href="https://da7xgjtj801h2.cloudfront.net/2015.2.624/styles/kendo.common.min.css" rel="stylesheet" type="text/css" />
<link href="https://da7xgjtj801h2.cloudfront.net/2015.2.624/styles/kendo.silver.min.css" rel="stylesheet" type="text/css" />
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://da7xgjtj801h2.cloudfront.net/2015.2.624/js/kendo.ui.core.min.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<!-- view -->
<div id="foo"
data-role="view"
data-show="onShow"
data-model="viewModel">
<div id="bar">
</div>
</div>
<!-- template -->
<script id="collapsible-template" type="text/x-kendo-template">
<div data-role="collapsible" data-expand="expandHandler">
<h3>
#= title #
</h3>
<table>
<tr>
<td>Line 1:</td>
<td>#= line1 #</td>
</tr>
<tr>
<td>Line 2:</td>
<td>#= line2 #</td>
</tr>
</table>
</div>
</script>
<script>
var app = new kendo.mobile.Application();
var data = [
{"title": "title1", "line1": "line 1", "line2": "line 21"},
{"title": "title2", "line1": "line 12", "line2": "line 22"}
];
function onShow(){
var template = kendo.template($("#collapsible-template").html());
$("#bar").html(kendo.render(template, data));
}
function expandHandler(){
console.log("expand");
}
</script>
</body>
</html>
Not sure how you do that mvvm way, go on with this initializing it on the javascript instead if it is okay
See the example :
var app = new kendo.mobile.Application();
var data = [
{"title": "title1", "line1": "line 1", "line2": "line 21"},
{"title": "title2", "line1": "line 12", "line2": "line 22"}
];
function expandHandler(){
console.log("expand");
}
function onShow(){
var template = kendo.template($("#collapsible-template").html());
$("#bar").html(kendo.render(template, data));
$(".test").kendoMobileCollapsible({
expand: expandHandler
})
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled</title>
<link rel="stylesheet" href="">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2016.2.714/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2016.2.714/styles/kendo.default.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2016.2.714/styles/kendo.mobile.all.min.css">
<script src="http://code.jquery.com/jquery-1.12.3.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2016.2.714/js/angular.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2016.2.714/js/jszip.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2016.2.714/js/kendo.all.min.js"></script></head>
<body>
<!-- view -->
<div id="foo"
data-role="view"
data-show="onShow"
data-model="viewModel">
<div id="bar">
</div>
</div>
<!-- template -->
<script id="collapsible-template" type="text/x-kendo-template">
<div class="test">
<h3>
#= title #
</h3>
<table>
<tr>
<td>Line 1:</td>
<td>#= line1 #</td>
</tr>
<tr>
<td>Line 2:</td>
<td>#= line2 #</td>
</tr>
</table>
</div>
</script>
</body>
</html>

Resources