how to include helpers in jsreport - javascript

I am using Dotnet Core 2.2 to generate report with JSReport (https://jsreport.net/)
I use local JsReport so I sent my template and data to the local server and get back the pdf. Now I need to format date in javascript, so I require to include moment.js into my templates. I have no idea how to do that.
In html I need to format StartDate to formated Date using moment.js
I have no idea how to include moment.js into template and how to add helpers.
For JSReport I am using engine chrome-pdf and handlebars as templating engine (https://jsreport.net/learn/handlebars)
I have tried to include moment.js in the
<script src="http://localhost:5000/public/js/moment.js"/>
<script>
function formatDate(date){
return moment(date).format("dd MMMM yyyy");
}
</script>
but when I called {{{formateDate startDate}}}} inside the html template, it seems the function/helpers not recognized.
My C# code:
[HttpGet("reporting")]
public async Task<IActionResult> Test(){
var sdr = await _repo.GetStaffDefaultRates();
var dto = _mapper.Map<List<StaffDefaultRate>, List<ReportDto>>(sdr);
var x = new {
bootstrapcss = "http://localhost:5000/public/css/bootstrap.min.css",
publicPath = "http://localhost:5000/public/",
message = "hello world",
today = DateTime.Now.ToString("dd MMM yyyy"),
staffRates = dto,
};
var staffRates = _fileRepository.ReadReportTemplate("StaffRates.html");
var rs = new ReportingService("http://localhost:5488");
var report = await rs.RenderAsync(new RenderRequest(){
Template = new Template(){
Recipe = Recipe.ChromePdf,
Engine = Engine.Handlebars,
Content = staffRates,
}, Data = x
});
var memory = new MemoryStream();
await report.Content.CopyToAsync(memory);
memory.Position = 0 ;
return File(memory, "application/pdf");
// return Ok(staffRates);
}
My templates:
<html>
<head>
<title> Staff Default Rates</title>
<link href="{{bootstrapcss}}" rel="stylesheet">
</link>
</head>
<body>
<div class="sticky-top">
<div class="row pt-3 header">
<div class="col-6 text-left">
<img src="http://localhost:5000/public/logo-full.jpg" width="100%"></img>
</div>
<div class="col-6 text-right"></div>
</div>
</div>
<div class="container">
<div class="row mt-5">
<div class="col-12 text-center">
<h2>Staff List {{today}}</h2>
<table class="table table-striped">
<thead>
<tr>
<th rowspan="2"> </th>
<th rowspan="2" colspan="1" class="align-middle">Staff Roles</th>
<th > Start Date </th>
</tr>
</thead>
<tbody>
{{#each staffRates}}
<tr>
<td>{{id}}</td>
<td>{{staffType}}</td>
<td class='text-center'>{{startDate}}</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
</div>
</div>
<div class="container">
<div class="row pb-3 footer fixed-bottom">
<div class="col-12 text-center">
<img src="http://localhost:5000/public/footer.jpg" width="100%"></img>
</div>
</div>
</div>
</body>
</html>

The minimal example would look like this.
var result = rs.RenderAsync(new RenderRequest {
Template = new Template
{
Content = "{{myFormat date}}",
Helpers = #"
const moment = require('moment')
function myFormat(d) {
return moment(d).format('dd MMMM yyyy')
}",
Engine = Engine.Handlebars,
Recipe = Recipe.ChromePdf
},
Data = new
{
date = DateTime.Now
}
}).Result;
result.Content.CopyTo(File.OpenWrite("report.pdf"));
Note your server should have local files access enabled. Otherwise the call require('moment') throws. The provided example will work as it is on default jsreport because it has moment module already installed. In case you want to use another custom module you need to install it using npm i mycustommodule.

Related

Using Django Models to assign HTML div through jQuery

for the last few days I've been trying to create a method in jquery using django models and I have found myself to be very out of my depth and would appreciate and explanation I can get. So currently I have a django model that has the following information : name, date, location, semester. I use the first 3 pieces of information in displaying my html, however, I want to use 'semester' to see what div tag my items go into.
The semester tag can either return 'Fall' or 'Spring' values is there a way I can use this to assign the components to the correct div. So if semester is Fall then it should go into the div with the id 'fall-races' and if its spring it should go to 'spring-races'
Currently I only have a jquery working where I get all the elements and assign it to the other div.
Thank you for your help and any possible advice.
<div class="flex-column">
<div class="header shadow-lg">
<h1 class="text-center py-3">
Fall Schedule
</h1>
</div>
<div id="fall-races">
{% for race in race %}
<div class="regatta-card my-2 mx-2 ">
<h2 class="center-text py-2">{{ race.date }}</h2>
<h1 class="text-center my-2">{{ race.name }}</h1>
<h3 class="text-center mb-3">{{ race.location}}</h3>
<h6 class="text-center">Recap</h6>
</div>
{% endfor %}
</div>
<input type="button" onclick="findChildren()" value="Click it" />
<div class="header shadow-lg">
<h1 class="text-center py-3">
Spring Schedule
</h1>
</div>
<div id="spring-races">
</div>
</div>
<script>
function findChildren() {
var objChl = document.getElementById('fall-races').children;
var msg = document.getElementById('spring-races');
msg.innerHTML = '';
for (i = 0; i < objChl.length ; i++) {
msg.appendChild(objChl[i]);
}
}
</script>
Maybe you want something like this:
Html:
<!-- Some html stuff -->
<div id="fall-races">
{% for race in race %}
<div class="regatta-card my-2 mx-2 ">
<h2 class="center-text py-2">{{ race.date }}</h2>
<h1 class="text-center my-2">{{ race.name }}</h1>
<h3 class="text-center mb-3">{{ race.location}}</h3>
<h6 class="text-center">Recap</h6>
<input type="hidden" value="{{race.semester}}" />
</div>
{% endfor %}
</div>
<!-- Some html stuff -->
JS:
<script>
function findChildren() {
var parent = document.getElementById('fall-races');
var objChl = parent.children;
var msg = document.getElementById('spring-races');
msg.innerHTML = '';
for (i = 0; i < objChl.length ; i++) {
const element = objChl[i];
var value = element.getElementsByTagName("input")[0].value;
if (value==="Spring"){
msg.appendChild(element);
parent.removeChild(element);
}
}
}
</script>
This is like the simplest way to achieve that, hope it helps you.

Javascript cannot find my imported constructor

I'm trying to implement model-view-control in a web app. I'm importing all the js in the bottom of the html but I'm getting this error:
Uncaught ReferenceError: SideController is not defined
at HTMLDocument.<anonymous> (app.js:9)
I've posted my relevant code below. How can SideController not be found? It is imported in the exact same way as SideBarView, which seems to import successfully.
<!DOCTYPE html>
<html lang="en">
<body>
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-12 sidebar collapse" id="sidebar">
<div class="noofpeople">
<div class="row noofpeople-wrapper">
<h4>My Dinner</h4>
<label>People <input id="numberOfGuests" type="number" class="form-control"></label><button type="button" id="plusButton"><span class="glyphicon glyphicon-plus"></span></button><button type="button" id="minusButton"><span class="glyphicon glyphicon-minus"></span></button>
</div>
</div>
</div>
<!-- jQuery -->
<script src="https://code.jquery.com/jquery.js"></script>
<!-- The application JavaScript code -->
<script src="js/app.js"></script>
<script src="js/model/dinnerModel.js"></script>
<script src="js/view/sidebarView.js"></script>
<script src="js/controllers/sidebarController.js"</script>
</body>
</html>
js/app.js:
$(function() {
//We instantiate our model
var model = new DinnerModel();
// And create the instance of ExampleView
var sidebar = $("#sidebar");
if(sidebar[0] != undefined){
var sidebarView = new SideBarView(sidebar, model);
var sidebarController = new SideController(sidebar, model);
}
var dishreel = $("#dishreel");
if(dishreel[0] != undefined){
var dishReelView = new DishReelView(dishreel, model);
}
});
js/controllers/sidebarController.js:
var SideController = function(container, model){
var plusButton = container.find("#plusButton");
var minusButton = container.find("#minusButton");
plusButton.onclick = function(){
model.incrNumberOfGuests();
};
minusButton.onclick = function(){
model.decrNumberOfGuests();
};
};
I missed a > on the last import.

MeteorJS get MongoDB ID in click event

I have the following mongo collection in my MeteorJS app:
//Server side, load all the images
Images = new Mongo.Collection('images');
Meteor.startup(() => {
if(Images.find().count() == 0){
for(var i = 1; i < 23; i++){
Images.insert({
src:"img_"+i+".jpg",
alt:"image "+i
});
}
}
});
I pass that to a template and that works. However, I then want to retrieve the MongoDB id of an image (id that is the primary key/unique ID in MongoDB). I do it with the following code:
//Client side, get the collection and load it to the template
Images = new Mongo.Collection('images');
Template.images.helpers({images:Images.find()});
Template.images.events({
'click .js-del-image': (event) => {
var imageId = event._id;
console.log(imageId);
}
});
This gives me undefined. What am I doing wrong? I thought this._id should give me the MongoDB ID.
For the record, This is my template, the _id attribute gets filled out:
<template name="images">
<div class="row">
{{#each images}}
<div class="col-xs-12 col-md-3" id="{{_id}}">
<div class="thumbnail">
<img class="js-image img-responsive thumbnail-img" src="{{src}}"
alt="{{alt}}" />
<div class="caption">
<p>{{alt}}</p>
<button class="js-del-image btn btn-warning">delete</button>
</div>
</div>
</div> <!-- / col -->
{{/each}}
</div> <!-- / row -->
</template>
The problem was in the declaration of a function:
(event) => { ... } seems to have _id of undefined.
function(event) {...} seems to have the correct context.
See this answer for further information about (event) => {...} vs function(){...} declarations.

How to loop through JavaScript object in HTML?

I want to loop through a JavaScript object and repeat an html script as many times as the object length.
Here, I have the following in a script tag
<script>
var obj;
ipcRenderer.on('requests-results', (event, hosSchema) => {
obj = hosSchema
})
</script>
obj is an array retrieved from Mongo database as the picture below shows:
and I have the following inside <body> tag:
<div class="row">
<div class="col-md-4 col-sm-4">
<div class="card">
<div class="card-content">
<span class="card-title">.1.</span>
<p>.2.</p>
</div>
<div class="card-action">
.3.
.4.
</div>
</div>
</div>
</div>
How can I loop through obj to repeat the code between <div> tag as many times as obj.length?
I would suggest you to use Handlebars as #Amit mentioned.
first move out the code inside <div id="page-inner"> as below:
<div id="page-inner">
</div>
<script id= "requests-template" type="text/x-handlebars-template">
<div class="row">
{{#each requests}}
<div class="col-md-4 col-sm-4">
<div class="card">
<div class="card-content">
<span class="card-title">{{this.fieldName}}</span>
<p>{{this.fieldName}}</p>
</div>
<div class="card-action">
{{this.fieldName}}
{{this.fieldName}}
</div>
</div>
</div>
{{/each}}
</div>
</script>
Then inside another script page of type text/javascript you create the requests and assigned obj/hosSchema to it as below:
<script type="text/javascript">
var requestInfo = document.getElementById('requests-template').innerHTML;
var template = Handlebars.compile(requestInfo);
var requestData = template({
requests: obj
})
$('#page-inner').html(requestData);
</script>
NOTE: you need handlebars package installed (npm install handlebars --save)
Use templating script like Handlebars.js, Mustache.js or underscore.js.
Check below link for more description.
http://www.creativebloq.com/web-design/templating-engines-9134396
Try this:
var divlist = document.getElementsByTagName['div'];
var duplicate = null;
var rowIndex = -1;
var found = false;
for(var i = 0;i<obj.length;i++)
{
if(!found)
for(var p = 0;p<divlist.length;p++)
{
if(rowIndex != -1 && duplicate != null)
{
//set a Boolean to true and break
found = true;
break;
}
if(divlist[p].className == "col-md-4 col-sm-4")
{
//copy the element
duplicate = divlist[p];
}
else if(divlist[p].className == "row")
{
//identify the row's index
rowIndex = p;
}
}
//append the duplicate
divlist[rowIndex].appendChild(duplicate);
}

How to draw dynamic JQ plot while saving a .aspx page as html file in C# .net

I'm developing a web based application using bootstrap.
I'm trying to save a .aspx page to html file in my application.
Here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.html.simpleparser;
using iTextSharp.text.pdf;
protected void btnExport_Click(object sender, EventArgs e)
{
string FileNamePath = #"D:\Test\Export.html";
StreamWriter sWriter = File.CreateText(FileNamePath);
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
pnlData.RenderControl(htw);
sWriter.WriteLine(sw.ToString());
sWriter.Close();
}
<panel id="pnlData" runat="server">
<style type="text/css">
//given css here
</style>
<div class="col-sm-12">
<div class="col-sm-12">
<!-- List starts -->
<ul class="today-datas">
<!-- List #1 -->
<li class="bred" style="width: 350px;">
<!-- Graph -->
<div class="pull-left">
<span id="todayspark5" class="spark"></span>
</div>
<!-- Text -->
<div class="datas-text pull-right">
<span>98%</span>Compliance</div>
<div class="clearfix">
</div>
</li>
<li style="width: 350px;">
<!-- Graph -->
<div class="pull-left">
<i class="icon-group"></i>
</div>
<!-- Text -->
<div class="datas-text pull-right">
<span>Yes</span>Reviewed</div>
<div class="clearfix">
</div>
</li>
<li style="width: 350px;">
<!-- Graph -->
<div class="pull-left">
<i class="icon-laptop"></i>
</div>
<!-- Text -->
<div class="datas-text pull-right">
<span>20</span>Outstanding Count</div>
<div class="clearfix">
</div>
</li>
</ul>
</div>
</div>
<div class="col-sm-12">
<div class="col-sm-6">
<!-- Widget -->
<div class="widget" id="DivHeader" runat="server">
<!-- Widget head -->
<div class="widget-head">
<div class="pull-left">
Compliance Chart</div>
<div class="widget-icons pull-right">
<i class="icon-chevron-up"></i><a href="#" class="wclose">
<i class="icon-remove"></i></a>
</div>
<div class="clearfix">
</div>
</div>
<!-- Widget content -->
<div class="widget-content">
<div class="padd" style="padding-bottom: 2px;">
<!-- Bar chart (Blue color). jQuery Flot plugin used. -->
<div id="curve-chart">
</div>
</div>
<div style="padding-bottom: 5px;">
<div class="legend" id="Legend" style="padding-left: 15px;">
<div class="header">
<span>Legend</span>
</div>
<table>
<tbody>
<tr>
<td>
<span class="label bred"><i class="icon-2x icon-only"></i></span><span style="margin-left: 7px;">
< 80% </span>
</td>
<td>
<span style="margin-left: 20px;" class="label byellow"><i class="icon-2x icon-only">
</i></span><span style="margin-left: 7px;">< 95% </span>
</td>
<td>
<span style="margin-left: 20px;" class="label bgreen"><i class="icon-2x icon-only"></i>
</span><span style="margin-left: 7px;">> 95% </span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- Widget ends -->
</div>
</div>
</div>
<script type="text/javascript">
var chartResult = null;
$(document).ready(function () {
var jsonurl = '/TestHandler/GetStatsData/Ajaxhandler.axd';
$.ajax({
async: false,
url: jsonurl,
dataType: "json",
data: { AccId: 1 },
success: function (data) {
InitJQPlot(data);
}
});
});
function InitJQPlot(data) {
var minValue = Math.round(Math.min.apply(Math, data.values)) - 1;
var testData = [];
var testLabel = [];
var j = 0;
for (var i = 0; i < data.Length; i++) {
testData.push([j, data.values[i]]);
testLabel.push([j, data.months[i]]);
j++;
}
var plot = $.plot($("#curve-chart"),
[{ data: testData, label: "Test Plot"}], {
series: {
lines: { show: true,
fill: true,
fillColor: {
colors: [{
opacity: 0.05
}, {
opacity: 0.01
}]
}
},
points: { show: true }
},
grid: { hoverable: true, clickable: true, borderWidth: 0 },
yaxis: { min: minValue, max: 100 },
xaxis: {
ticks: testLabel
},
colors: ["#fa3031"]
});
}
</script>
</panel>
<asp:Button ID="btnExport" OnClick="btnExport_Click" runat="server" Text="Export To HTML" />
I have given my css within <style> element.I have included jquery.js,jquery-ui.min.js,jquery.flot.js,jquery.flot.resize.js,jquery.flot.pie.js,
jquery.flot.stack.js,sparklines.js,sparkline-index.js
i'm getting that dynamic chart in .aspx page but its is not getting generated in html file .. i'm just getting a blank space in that <div id="curve-chart">
I'm not getting an output html file with dynamic chart.
Please help me out to create html file with dynamic chart.
So you're opening the html file from D:\Test\Export.html? If so, the link to generate the graph data: var jsonurl = '/TestHandler/GetStatsData/Ajaxhandler.axd'; is relative, so while you run it on your server it can find the correct .axd file, whereas when it is just on a local file system it doesn't know which server to get the information from.
If you make the URL absolute, eg. http://servername/TestHandler/GetStatsDAta/Ajaxhandler.axd, you might find that it works although there is the potential for the browser having security concerns about a local file going off to a server.
I have declared testData and testLabel globally and assigned value from page load using `JavaScriptSerializer'. now i'm able create html file with dynamic chart.
in code behind file :
public List<object> testDataList = new List<object>();
public List<string> testLabelList = new List<string>();
protected void Page_Load(object sender, EventArgs e)
{
//Load data to testDataList and testLabelList
}
protected string JsontestDataArray
{
get
{
var myArray = testDataList.ToArray();
return new JavaScriptSerializer().Serialize(myArray);
}
}
protected string JsontestLabelArray
{
get
{
var myArray = testLabelList.ToArray();
return new JavaScriptSerializer().Serialize(myArray);
}
}
in .aspx page:
$(document).ready(function () {
var testDataList = {values: <%= JsontestDataArray %>};
for (var i = 0; i < testDataList.values.length; i++){
testData.push([i, testDataList.values[i]]);
}
var testLabelList = {values: <%= JsontestLabelArray %>};
for (var j = 0; j < testLabelList.values.length; j++){
testLabel.push([j, testLabelList.values[j]]);
}
});
Now i'm able to get data to load my dynamic chart.

Categories