Sending JSON Data to printer in PDF format Angular - css

I am getting JSON data from API, after getting that data i need to send that JSON data to print in pdf format. Please help me to solve this in Angular.
Reframing my question: I am now getting HTML data from API in an JSON format and I successfully rendered it on component but I am applying CSS for page-break-before is not working. Can anyone please help me out in it.
When I create in simple index.html file as a static data it is working but same with Angular component it is not working whether it is static or dynamic.
I tried
#media all {
.page-break { display: none; }
}
#media print {
.page-break { display: block; page-break-before: always; }
}
My HTML Code
<div class="page-break"></div>
<p>Date: 27/02/2020 </p>
<p>Sub: Request for ..............</p>
<p>WRT the BG number <b>123456789</b></p><br><br><br>
<p>Account number: 0000000000</p>
<p>Acccount Name: ABC</p>
<p>IFSC: ABC12456</p><br><br>
<p>Regards</p>
<div class="page-break"></div>
<p>Date: 27/02/2020 </p>
<p>Sub: Request for ..............</p>
<p>WRT the BG number <b>123456789</b></p><br><br><br>
<p>Account number: 0000000000</p>
<p>Acccount Name: ABC</p>
<p>IFSC: ABC12456</p><br><br>
<p>Regards</p>

One way to achieve this is with html2canvas and jsPdf. First you convert your HTML to an image with html2canvas and then print the image with jsPdf
const input = document.getElementById('print-container');
html2canvas(input)
.then((canvas) => {
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({
orientation: 'landscape',
});
const imgProps = pdf.getImageProperties(imgData);
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width;
pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight);
pdf.save('download.pdf');
});
See this Stackblitz I made: https://stackblitz.com/edit/angular-p1a7xn
Another way is to use jsPdf without html2canvas. Then you need to layout and style the pdf for yourself

Take a look to this library: http://pdfmake.org/#/
It's awesome!
Take a look to their playground here: http://pdfmake.org/playground.html
Basic example code:
const dd = {
content: [
'First paragraph',
'Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines'
]
}
This will create 2 lines in the PDF.
Their npm: npm i pdfmake

Related

Inject CSS variable names that come form the server (Angular 12)

I'm trying to find the best solution to inject css variables into angular application (currently using Angular 12).
This is the code I'm using:
private injectStyles(data: any) {
const styles = this.document.createElement('STYLE') as HTMLStyleElement;
styles.id = 'dynamic-css';
this.test = `:root {
--main-bg-color: black;
}`;
styles.innerHTML = this.test;
this.renderer.appendChild(this.document.head, styles);
}
This code is being executed on app.component.ts file and this works quite well, i can use this css variable throughout the whole application.
What I'm trying to achieve now is to extend the this.test Object with data that comes from the server and apply these custom css values that were set on my Visual settings module before.
Css variables must not have "" quotes.
"--button-color": "#a86c6c" (this is what I get from the server) and I would like to inject this property without quotes on the this.test Object and I can't do that. Any ideas?
Any help is highly appreciated,
Thanks.
Object.keys is your friend
let dataString = '';
Object.keys(data).forEach(key => {
dataString += `${key}: ${data[key]};`
});
this.test = `:root {
--main-bg-color: black;
${dataString}
}`;
If needed, you may need to add quote to the value like this
`dataString += `${key}: "${data[key]};"`

Dynamically switch global CSS for Angular8 app (client branding)

I want to dynamically switch Angulars global CSS files based on which client is connecting. This will be used for client-branding purposes, including fonts, colors, photos, headers, footers, button-styles, etc.
Each client has provided us with a CSS file, which we need to integrate into our app. We have hundreds of clients.
Current solution is to try and override the CSS of individual components at load. This is bad because it adds a lot of boilerplate:
Html:
<link id="theme" rel="stylesheet" href="./assets/stylesheets/{{cclientCode}}.css">
ts:
ngOnInit() {
this.service.clientCode.subscribe(clientCode => this.clientCode = clientCode);
}
My workaround isn't working because the link html is called before the {{}} has a chance to load in the value.
I'm also not motivated to fix my workaround because its just that -a workaround. Instead, I want to implement something that works globally, without any per-component boilerplate.
What I want is the ability to dynamically switch the global Angular style for each client. So something like:
"styles": [
"src/assets/stylesheets/angular_style.css",
"src/assets/stylesheets/client_style.css"
]
Where client_style.css is served differently to each client.
I've found a solution that I think is workable. It definitely has issues though, so if anyone has their own answer, please still share!
First, I added a clientCode String field to SessionDataService, a global service I use to move component-agnostic data around my app:
export class SessionDataService {
clientCode: BehaviorSubject<String>;
constructor(){
this.clientCode = new BehaviorSubject('client_default');
}
setClientCode(value: String) {
this.clientCode.next(value);
}
}
Then, inside app.component.ts, I added a BehaviorSubject listener to bring in the value of clientCode dynamically:
public clientCode: String;
constructor(private service : SessionDataService) {
this.service.clientCode.subscribe(clientCode => this.clientCode = clientCode);
}
Next, I added a wrapper around my entire app.component.html:
<div [ngClass]="clientCode">
--> ALL app components go here (including <router-outlet>)
</div>
So at this point, I've created a system that dynamically adds client-code CSS classes to my components, including all children :)
Finally, I just have to write CSS rules:
.ClientOne p {
color: red;
}
.ClientOne .btn {
background-color: red;
}
.ClientTwo.dashboard {
height: 15%;
}
I hope this helps somebody! Essentially the "trick" here is to add a ngClass that wraps the entire app, and then justify all client-specific CSS rules with their client code.

Modify HTML tag from dangerouslySetInnerHTML in React

I am building a Gatsby Blog using React/Gatsby & the Wordpress API.
I render an excerpt of the latest articles on the landing page like so:
<span
className="mb-0"
id="excerpt-wrapper"
dangerouslySetInnerHTML={{ __html: this.props.post.node.excerpt}
/>
The problem is, my this.props.post.node.excerpt comes with an unwanted wrapping <p> tag. This tag inherit from Bootstrap CSS as I am using Bootstrap 4 in my whole project, and from the user agent stylesheet.
Hence I need to find a way either to :
get rid of the wrapping p tag
modify the CSS once the excerpt is mounted
I tried the following solution:
componentDidMount() {
this.removePTagMargin();
}
removePTagMargin = () => {
const excerptWrapper = document.querySelector("#excerpt-wrapper");
excerptWrapper.firstChild.style.marginBottom = "0px !important"
excerptWrapper.firstChild.style.marginBlockEnd = "0px !important"
}
but it does not work (maybe because it executes before the WP API call is done ?).
How can I solve my problem ?
This is assuming the excerpt comes from gatsby-transformer-remark.
You can choose the format of your excerpt in your GraphQL query for the post, it looks like the format you're using is HTML, you want PLAIN:
https://www.gatsbyjs.org/packages/gatsby-transformer-remark/#format
Try modifying your query by putting the format parameter on the excerpt field:
{
allMarkdownRemark {
edges {
node {
excerpt(format: PLAIN)
}
}
}
}
Edit: Hacky way of removing the <p> tags due to the inefficiencies in this gatsby-source-wordpress plugin.
Add a helper called removeParagraphTags this will simply trim the first three chars from the string and the last 4 chars from the string.
removeParagraphTags (excerpt) {
return excerpt.substr(3, excerpt.length - 7)
}
Then you can use this helper when setting the excerpt HTML.
dangerouslySetInnerHTML={{
__html: this.removeParagraphTags(this.props.post.node.excerpt)
}}

How to display Emoji in React App

I would like to display emojis on my webpage in a react chat app. The plan is to give the user a list of emojis to select from. How do I use the codes like '1F683' and have them display the emoji on the page? I need to support Chrome.
I am able to use css to show the emoji.
<div className="smiley"></div>
.smiley:after {
content: "\01F683";
}
I can also have a list of images and map them to the code and display an img element per emoji.
Is there another way and which is the best way to do this?
I am maybe late to the party but I needed to conditionally render different emojis by the same component, so for me the easiest way was:
Go to https://unicode.org/emoji/charts/full-emoji-list.html
Find needed emojis, for example U+1F609 and use it as a string of a hex number 0x1F609 with String.fromCodePoint in your code — see below.
Create one little component to satisfy eslint rule which would otherwise throw an error
Emojis should be wrapped in <span>, have role="img", and have an accessible description with aria-label or aria-labelledby jsx-a11y/accessible-emoji:
const Emoji = React.memo(({ className, label, symbol }) =>
<span className={className} role="img" aria-label={label}>
{String.fromCodePoint(symbol)}
</span>)
export default Emoji
So then somewhere else you can use it as:
class MagnificentComponent extends PureComponent {
getEmojiConditionally = () => this.props.happy ? '0x1F60A' : '0x1F61E'
render = () =>
<SomeComponentWhereINeedEmoji>
<Emoji symbol={this.getEmojiConditionally(} />
</SomeComponentWhereINeedEmoji>
}
All emojis are pretty much standardized with the format at Emoji Cheat Sheet, so your given example above (\01F683) maps to railway_car in the Emoji Cheat Sheet.
It might be a better idea to store your emojis with these identifiers and map it to the actual emojis later on, without worrying about encoding the actual emoji (🚃) themselves, or not being able to tell/remember the actual emoji represented by the Unicode sequence (\01F683).
If you wish to map this human-readable identifier to the actual Unicode sequence/symbol itself, you have a few options, using railway_car as an example:
Twemoji Awesome
Twemoji Awesome is like Font Awesome, but with Twitter Emojis.
You can then insert an emoji like this, just like Font Awesome.
<i class="twa twa-railway-car"></i>
This will output the corresponding SVG:
Emoji Dictionary
There's an npm package aptly named emoji-dictionary that allows you to map the emoji name to the Unicode character, if you wish to use default the browser's default emoji renderer.
The usage will then look like this:
emoji.getUnicode("railway_car");
This returns 🚃 (which would display on modern browsers/might break on older browsers/etc).
We have the unicode of emojis in W3C .
It is in the range of {. Hex 2600-26FF.}.
Thus, you can generate it without CSS.
Check example below 👇🏼
class Emoji extends React.Component {
render() {
const {title, code} = this.props;
return <span className="emoji" title={title}>{code}</span>
}
}
class App extends React.Component {
renderEmojis() {
const rangeEmojis = Array.from({length: 256}, (v, k) => (k + 9728).toString(16));
return rangeEmojis.map((code, index) => <Emoji code={unescape ('%u' + code)} title={"My code is :"+code} key={'emj'+index} />)
}
render() {
return (
<div>
{this.renderEmojis()}
</div>
)
}
}
ReactDOM.render(<App />, document.querySelector('#chat'))
.emoji {
border: solid 1px #3e3e3e;
width: 50px;
height: 50px;
cursor:pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<section id="chat" />
They are many ways to use emoji's in react. With NPM and also without it by a "span" tag.
<span role="img" aria-label="arrow">➡️</span>
I find this simple and easy to use.
React code for Grinning face with big eyes:
<div>
{String.fromCodePoint('0x1f603')}
</div>
Output:
😃
Full Emoji List, v15.0 - https://unicode.org/emoji/charts/full-emoji-list.html
--
Putting this here just incase anyone else stumbles on this post looking for what I needed.
<p>
After a lot of Googling and reading I just copy/pasted the emoji, it seems to work fine 🤷‍♂️.
</p>
To get the emoji I went to Discord sent the emoji I needed and copy/pasted it into my code and it shows up on screen.

Making a multiple objects appear one after another using Firebase

Edited a bit to try and explain this better
I have a problem in which i'm not sure how to even start to go about solving. It's also very hard to explain.
Basically, I have a storage location in Firebase that looks like this:
(in this image it only shows one storage location. later there is another with a title of 'Test' and a body of 'As you can see, this messes up')
What I want to do is have it so that when I use this code:
html file:
<div class="span8" id="verticalLine">
<h2 id="main-header"><center>Latest news</center></h2>
<div id="newsDivHead"></div>
<br/>
<div id="newsDiv"></div>
<script>
var newsData = new Firebase("https://agn.firebaseio.com/web/news/mc/")
newsData.limit(10).on('child_added', function (snapshot) {
var message = snapshot.val();
$('<div/>').text(message.body).appendTo($('#newsDiv'));
$('<div/>').text(message.title).appendTo($('#newsDivHead'));
$('#newsDiv')[0].scrollTop = $('#newsDiv')[0].scrollHeight;
});
</script>
<!---
$('<div/>').text(message.body).prepend($('<em/>')
.text(message.title+': ')).appendTo($('#newsDiv'));
$('#newsDiv')[0].scrollTop = $('#newsDiv')[0].scrollHeight;
});
--->
</div>
</div>
I want it to give a result like this:
Notice the formatting of the title and the break.
But unfortunately it comes out like this:
What I want to happen is it formats the value stored in message.title so that it appears above the message.body and is formatted in the format (or something similar). I have realised that this is not possible using the two div tags, I can only use the one.
So what do I do? Is this even possible? The title and text are in the 'varibles' (firebase ref) message.title and message.body respectivley (As you can see in the code.)
Any Help gladly appreciated!
This doesn't have anything to do with Firebase, but is rather a HTML issue. You have two divs in your HTML, one to show titles and another to show content. Don't do this and use CSS classes instead of visually separate titles from text.
<div class="span8" id="verticalLine">
<h2 id="main-header"><center>Latest news</center></h2>
<div id="content">
</div>
</div>
var newsData = new Firebase("https://agn.firebaseio.com/web/news/mc/")
newsData.limit(10).on('child_added', function (snapshot) {
var message = snapshot.val();
var body = $('<div/>').class('body').text(message.body);
var title = $('<div/>').class('title').text(message.title);
$('<div/>').append(title).append(body).appendTo($('#content'));
});
In your CSS, set the styles for the classes 'body' and 'title' as you do currently for your 'newsDiv' and 'newsDivHead' IDs:
.body {
font-size: 12px;
}
.title {
font-size: 18px;
font-weight: bold;
}

Resources