Hi @admin ... that worked nicely. Thanks very much for the pointer.
Posts made by ifrantar
-
RE: Adding an '@ index' to pdfAddPageItem
-
Adding an '@ index' to pdfAddPageItem
Hi
I have this code where I'm looping through an array of data:
{{#each assumptions.operatingProfile.leaseOperation }} <div class="timeline__global tg__color-{{ 1 }}"> <h2 class="mb-2">Lease {{ 1 }}</h2> {{{pdfAddPageItem subSections="Lease {{1}} - Contracted" subSectionsClass="toc__bold"}}} .... .... etc. .... {{/each}}
When I render the table of contents, it seems that the
{{1}}
in thepdfAddPageItem
is not parsed. The{{1}}
in the<h2>
tag works well, though. Here's a sample section of how my table of contents is coming:Edits...................................................................................3
Operating...........................................................................4
Lease {{1}} - Contracted.........................................4
Operating Profile...............................................................4
Workscope........................................................................4
Lease {{1}} - Contracted.........................................4
Operating Profile...............................................................4
Workscope........................................................................5
Non-Leased Operator.......................................................6Is there any optimal way I can pass the value to the attribute
subSections="Lease {{1}} - Contracted"
?Many thanks in advance!
-
RE: Programaticaly need to disable a template if it comes with no data or null
Thanks a mill @Happy-Patel and @admin
I think you second solution, @admin is what I needed. I checked there and is working perfectly. I needed to dynamically get to the operation enabling and disabling of a template. I'll explore the other options as I think there's of bit of that I need to account for.
Thanks both of you for your time! ;)
-
Programaticaly need to disable a template if it comes with no data or null
Hi,
I'm having the following problem that I don't know how to solve and the solutions I come up with are not entirely working.
To start, I have a report that has this line to start a number of templates:
{{{pdfCreatePagesGroup reportName="Valuation" logoImageData=logoImageData}}}
and it's pdf util operations as this:
So, what I want to do is to programmatically disable (untick) the, for instance,
valuations-template-ecd
in the screenshot above, if its data come asnull
I was trying to wrap the whole template into an
{{#if}}
statement from<html> to </html>
and closing the{{ /if }}
but, while this solution partially works, for some reason is rendering two Table of Contents page (where it should be only one) and one empty.Overall I need to disable a template (I cannot manually do it from the pdf utils operations tab), based on the data received as
null
.Thank you endlessly in advance for any help :)
-
RE: Populating the Table of Content with subheaders extracting text from <H2>'s in template
Hi...
Ah brilliant! Thanks for pointing those out. I checked this one out as well from your util link. I have now a couple of solid use cases to work on - https://playground.jsreport.net/w/anon/0~cRmrQ~
Thanks again 🙏
-
Populating the Table of Content with subheaders extracting text from <H2>'s in template
Hi I'm struggling to populate a Table of Content where I want to incorporate subheaders in the template as part of the Table of Content.
For instance and to start with, here's an example of how it currently looks on my current setup:
This is all fine and this is achieved with this code in the helper section:
function tableOfContents (pdfPages) { function onlyUnique(value, index, self) { return self.indexOf(value) === index; } const sections = pdfPages.map((d) => d.group?.title ?? "Blank").filter((d) => d !== "Blank").filter(onlyUnique) const contents = []; for (const section of sections) { let firstPageOfSection = 0; let firstPageSeen = false; for (let i = 0; i < pdfPages.length; i++){ if (pdfPages[i].group?.title === section) { if(!firstPageSeen) { firstPageOfSection = i + 1; firstPageSeen = true; } } } contents.push({ sectionName: section, firstPageOfSection: firstPageOfSection }) } return contents; }
And here in the template:
<ul class="toc__list"> {{#each (tableOfContents $pdf.pages)}} <li class="toc__item"> <span class="toc__title">{{this.sectionName}}</span> <span class="toc__spacer"></span> <span class="toc__page">{{this.firstPageOfSection}}</span> </li> {{/each}} </ul>
So... what I want to do is to have something like this in the Table of content:
- Executive Summary ................................. 1
- Pricing ...................................................... 2
- Subheader 1 ................................... 2
- Subheader 2 ................................... 3
- Subheader 3 ................................... 3
- and so on...
So, the subheaders, and here is where I'm struggling with, which is getting them from the template by targeting all the <h2> tags with a class name, i.e.
<h2 class="toc__listed">
I was trying to do something like this:
function tableOfContents(pdfPages) { function onlyUnique(value, index, self) { return self.indexOf(value) === index; } const sections = pdfPages.map((d) => d.group?.title ?? "Blank").filter((d) => d !== "Blank").filter(onlyUnique) const contents = []; for (const section of sections) { let firstPageOfSection = 0; let firstPageSeen = false; const subsections = []; for (let i = 0; i < pdfPages.length; i++) { if (pdfPages[i].group?.title === section) { if (!firstPageSeen) { firstPageOfSection = i + 1; firstPageSeen = true; } // Extract h2 headers with class .toc__listed from page content const h2Regex = /<h2 class="toc__listed".*?>(.*?)<\/h2>/g; const matches = pdfPages[i].content.match(h2Regex); if (matches) { const subSections = matches.map(match => match.replace(/<\/?h2.*?>/g, '').trim()); subsections.push(...subSections); } } } contents.push({ sectionName: section, firstPageOfSection: firstPageOfSection, subsections: subsections }); } return contents; }
And then update the template with something like this to match this updated code:
{{#each (tableOfContents $pdf.pages)}} <li class="toc__item"> <span class="toc__title">{{this.sectionName}}</span> <span class="toc__spacer"></span> <span class="toc__page">{{increment this.firstPageOfSection 1}}</span> <ul> {{#each this.subsections}} <li>{{this}}</li> {{/each}} </ul> </li> {{/each}}
But I don't seem to go anywhere without running in to a number of errors.
So, my question would be:
- Am I close with this to achieve what I want to get and if you point me toward what I might be missing? OR
- Is there a better approach I should be considering when working with Table of Contents?
Many thanks in advance for any help you guys can provide!
-
RE: Using handlebars {{each}} helper to populate a javascript variable array
Ok, this worked.
const mxEventsData = {{{toJS MXEvents}}}; const chartData = []; mxEventsData.forEach((event) => { event.part.forEach(({ partName, totalEventsCost }) => { chartData.push({ date: event.date, totalEventsCost: Number(totalEventsCost.replace(/\D/g, '')), // Format to numeric value partName, }); }); });
Thanks a million, once again!
-
RE: Using handlebars {{each}} helper to populate a javascript variable array
Ahh brilliant! I think I'm getting somewhere with your pointer. Thanks a mill @bjrmatos ! I'll report back, how it goes.
-
Using handlebars {{each}} helper to populate a javascript variable array
Hi,
This might be a bit silly since I'm a bit bit new with JSReport, but I'm trying to do something like this to iterate over my data source and compile with the
{{#each}}
helper in the template where I have an inline<script>
I'm using for a chart. At the moment, this doesn't seem to be working:const chartData = [ {{#each MXEvents}} { date: "{{this.date}}", {{#each this.part}} partName: {{this.partName}}, totalEventsCost: {{this.totalEventsCost}} {{/each}} }, {{/each}} ]
The above
{{each}}
theoretically should work, because if I do the same in the template, like this, it populates it perfectly:<ul> {{#each MXEvents }} <li>{{this.date}}</li> <ul> {{#each this.part}} <li>{{this.partName}} - {{this.totalEventsCost}}</li> <ul> {{#each this.event}} <li>{{ this.eventName }}</li> {{/each}} </ul> {{/each}} </ul> {{/each}} </ul>
I'm not sure if I'm doing it right or if there is a better way to do this. In essence, what I'm trying to achieve is to bring this data into the javascript, so I can loop it through and populate it for a Highcharts.js code.
Any help pointing me in the right direction will be highly appreciated 🙏. Not sure if it'll be of any use, but here is the full code I'm using.
//<!-- chart container. --> <div id="mx_events_chart" class="mb-4"></div> <script> // Extract the data and prepare the series for Highcharts const chartData = [ {{#each MXEvents}} { date: "{{this.date}}", {{#each this.part}} partName: {{this.partName}}, totalEventsCost: {{this.totalEventsCost}} {{/each}} }, {{/each}} ] // console.log(chartData); //const testing = document.getElementById('testing'); //testing.textContent = JSON.stringify(chartData); // Extract unique dates and partNames const uniqueDates = []; const uniquePartNames = []; chartData.forEach(({ date, partName }) => { if (!uniqueDates.includes(date)) { uniqueDates.push(date); } if (!uniquePartNames.includes(partName)) { uniquePartNames.push(partName); } }); // Create an object to store series data based on partName const seriesData = {}; // Initialize seriesData with zero values for each date uniquePartNames.forEach((partName) => { seriesData[partName] = { name: partName, data: uniqueDates.map((date) => { const dataPoint = chartData.find((data) => data.date === date && data.partName === partName); return dataPoint ? dataPoint.totalEventsCost : 0; }), }; }); // Convert seriesData object into an array of series const chartSeries = Object.values(seriesData); // Create the Highcharts chart Highcharts.chart('mx_events_chart', { chart: { type: 'column', }, title: { text: '', }, yAxis: { title: { text: '' } }, xAxis: { categories: uniqueDates, }, credits: { enabled: false, }, plotOptions: { column: { stacking: 'normal' }, series: { animation: false, }, }, series: chartSeries, }); </script>