Convert html to pdf using jspdf in angular - html

I have a div tag with all the content which i need to convert to pdf. It is a report layout.
The function below is found inside the .ts file which is called on a button click. On button click the id of the div tag is given to the function to get all the html elements as content to be exported as pdf.
import jsPDF from 'jspdf';
#ViewChild('pdfTableJspdf', { static: false }) pdfTableJspdf!: ElementRef;
downloadAsPDF_UsingJsPdf() {
let pdf = new jsPDF('p','pt','a4');
pdf.html(this.pdfTableJspdf.nativeElement, {
callback: (pdf) => {
pdf.save('sample.pdf');
},
});
}
Problem encountered is that the library jspdf is unable to export the whole content with its appropriate layout.
My requirement is to export a given html element to pdf without using autoTable and canvas.

Related

Replace bokeh object inside div on-click

I'm able to get the bokeh object to render properly inside a div on the webpage. The bokeh object is returned via Flask and is generated based on a user-click. However, my problem is that on every user-click, the new bokeh object that is produced, gets appended to the div.
I've read about the .html() way of replacing content, and I've also read about document.getElementById, but I'm not sure how to replace my div content and avoid the append. Any help is appreciated.
The relevant snippet from my index.html
rows.forEach(row => {
row.addEventListener("click", () => {
var pic = <<my_url>> + ($(row).attr("data-href"));
$.ajax({
data : {},
dataType: "json",
type : 'GET',
url : <<my flask app path>>
})
.then(function(response) {return response;})
.then(function(item) {
Bokeh.embed.embed_item(item);
})
});
});
emptying the contents of the div on-click is the approach I took to resolve my situation. i.e.,
$(div).empty();

How can I display dynamic HTML having Vue variables inside?

I am trying to make the page content dynamic. I am using ck-editor in which i added html content and used the same vue variables inside it which i declared in the vue file where i want to show ck-editor data. I found a similar post vuejs - “editing” html inside variable
which works fine if i write the html inside a variable. But in my case, i am saving data in database. It is saving properly with html tags, without converting the tags. When i get data using axios it returns it in form of string. And i used vue variable to display that html.
Here is my code for better understanding:
<div v-html="htmlText"></div>
new Vue({
el: '#app',
created() {
this.getSalesContent();
},
data: {
salesContent: '',
pageName: 'Sales',
salesNumber: '987-586-4511'
},
computed: {
htmlText() {
return `${this.salesContent}`;
//return this.salesContent;
}
},
methods: {
getSalesContent(){
axios.get('api/Sales').then(({ data }) => { // getting data from DB
this.salesContent = data.sales; //data.sales have this.pageName and this.salesNumber variables
});
}
}
});
Here is the example of data saved in db:
<p style="font-weight:bold"><span style="color:red">{{pageName}}</span>,</p>
<p style="font-weight:bold"><span style="color:red">${this.pageName} ${this.pageName}</span></p>
<p style="font-weight:bold">Contact Sales at ${this.salesNumber} {{salesNumber}}</span></p>
I used variables in all possible ways. But on the page they are printing in it the same way i saved it. Here is the output:
screenshot
Can anyone help me make it working.
Thanks in Advance.
According to the docs this does not seem possible:
https://v2.vuejs.org/v2/guide/syntax.html#Raw-HTML
Particularly:
The contents of the span will be replaced with the value of the
rawHtml property, interpreted as plain HTML - data bindings are
ignored.
You could as suggested in that answer just use a computed based on what you get from the server.
IMHO since the salesContent is fetched from db, it's a plain String. Thus nor vuejs or vanilla javascript will replace the inline variables with their values. (It may be possible by using eval, but it's totally out of question...) You should manually do that with String replace function. Like the following:
<p style="font-weight:bold"><span style="color:red">{{pageName}}</span>,</p>
<p style="font-weight:bold">Contact Sales at {{salesNumber}}</span></p>
methods: {
getSalesContent(){
axios.get('api/Sales').then(({ data }) => { // getting data from DB
let salesContent = data.sales; //data.sales have this.pageName and this.salesNumber variables
salesContent = salesContent.replace(/{{pageName}}/g, this.pageName)
salesContent = salesContent.replace(/{{salesNumber}}/g, this.salesNumber)
this.salesContent = salesContent
});
}
}

Angular2 e2e not accessing Boostrap modal element

I'm running some e2e tests on an Angular2 app. One test involves clicking a button to open a Bootstrap modal. Even though I simulate the click of the button in my e2e test, it seems I cannot access the modal.
I'm currently just trying to run a simple test to click the button, open the modal, and check the text in an h4 element within the modal.
app.po.ts:
import { browser, element, by } from 'protractor';
export class SolarUi4Page {
navigateTo() {
return browser.get('http://localhost:4200/');
}
getAddButton() {
return element(by.css('.icon-plus'));
}
//2nd and 3rd lines attempt to do the same thing. Neither work
getH4() {
//return element(by.css('main-page')).element(by.id('data')).getText();
//return element(by.css('add-validation')).element(by.tagName('h4')).getText();
return element(by.css('h4')).getText();
}
}
app.e2e-spec.ts:
import { SolarUi4Page } from './app.po';
describe('solar-ui4 main page', function() {
let page: SolarUi4Page;
beforeEach(() => {
page = new SolarUi4Page();
});
it('should add new value to array/table and display it', () => {
page.navigateTo();
let addButton = page.getAddButton();
addButton.click();
expect(page.getH4()).toEqual('Add Data Point');
});
});
app.component.html (contains three custom components):
<main-page></main-page>
<add-validation></add-validation>
<delete-validation></delete-validation>
I am able to access any element inside the main-page component via syntax like the first commented out line in getH4() method. It seems I cannot access anything from the add-validation element, which is my Bootstrap modal. I'm assuming it is because that HTML is not present on the page on load, but shouldn't addButton.click(); trigger the modal to open so it IS present?
You might need to wait for the popup to be visible via browser.wait():
var EC = protractor.ExpectedConditions;
var elm = element(by.css('h4'));
browser.wait(EC.visibilityOf(elm), 5000);
expect(elm.getText()).toEqual('Add Data Point');

Include directive before html render

I tried wrapping my head around the following problem:
I have a html string which I render using ng-bind-html
I managed to change a given placeholder (in the html string) with a directive (or more). For example I have: [placeholder]test[/placeholder] and replaced with <my-directive></my-directive> for a certain functionality.
This approach is needed to make some content dynamic.
When rendering the html string I notice that the directive is missing, I understand, but is there a way to render it and make the directive functionally?
P.S:
Tried rendering it as a normal string but the html is escaped
Tried using $sce.trustAsHtml()
I cannot apply $compile(element.contents())(scope); since the directive is not triggered
I have managed to do achieve this by doing the following:
Add the directive in the html:
<my-directive update-data-trigger="someObject.content" data="someObject"></<my-directive>
The directive:
app.directive("myDirective", function ($compile) {
return {
replace:true,
restrict: "E",
scope: {
//Data holds the html in the content attribute
data: '=',
updateDataTrigger: '='
},
link: function ($scope, element) {
//Add a watcher to refresh data because the loaded data passed is async
$scope.$watch('updateDataTrigger', function(){
//Check if data passed has been loaded with our desired object
if($scope.updateDataTrigger != null) {
//Do some content manipulation here
//Append directives to the content as well
//render as html
element.html(data.content);
$compile(element.contents())($scope);
}
});
}
}
});

Unable to autofocus input element in Firefox add-on tab

I used .open() to create a tab displaying the HTML in data/search.html and attached data/search.js as a content script file.
var tabs = require("sdk/tabs");
var data = require("sdk/self").data;
function executeSearch () {
/* set up search tab */
tabs.open({
url: data.url("search.html"),
onReady: function (tab) {
var worker = tab.attach({
contentScriptFile: data.url("search.js")
});
worker.port.on("searchtext", function (wordsJson) {
worker.port.emit("matchingPages", JSON.stringify(hlutils.matchingPages(wordsJson)));
});
}
});
}
The HTML displays correctly and the content script runs properly, but in the HTML file (which is in valid HTML5) the autofocus property of an input element is not honored. Basically there is no cursor in the page as displayed, and no input can be made without clicking into the input element. I tried doing it the old-fashioned way by using
document.getElementById("search").focus();
in the content script file, and also in a script element in the HTML file (below the referenced element), all to no avail.
Finally figured it out. Had to add the following to the content script file:
window.addEventListener("load", function (event) {
document.getElementById("search").focus();
});