I'm using Froala Editor in my Angular project, and I'm relatively new to it.
In my setup, I have a single Froala editor instance shared across multiple pages. When I switch between pages, I clear the content of the previous page and reinitialize the editor with the new content.
I want to add a custom "Print" button to the Froala toolbar that prints the current content of the editor. I followed examples like this one: Froala Print Button Example, and it works fine in that context.
However, in my Angular project, when I click the print button, the print dialog opens but the content area is blank — it doesn’t show the editor content.
I suspect it might be related to how I'm reinitializing the editor when switching pages, but I'm not sure. Has anyone faced this issue or can suggest how to properly print the content from a reinitialized Froala editor?
Here is my code:
private editorOptions() {
const newUniqueId = this.generateUniqueId();
const loggedInUserId = this.userInfo?.userId;
this.options = {
key: Froala_Constants.LICENSE_KEY,
attribution: false,
fontFamilyDefaultSelection: 'var(--font-NeueHaasDisplayLight)',
fontFamily: {
'Neue Haas Display Light': 'var(--font-NeueHaasDisplayLight)',
},
fontSizeDefaultSelection: '12',
charCounterCount: false,
placeholderText: 'Create Your Template Here!',
imageUpload: true,
imageDefaultAlign: 'left',
imageDefaultDisplay: 'inline-block',
// Set max image size to 5MB.
imageMaxSize: 5 * 1024 * 1024,
// Allow to upload PNG and JPG.
imageAllowedTypes: ['jpeg', 'jpg', 'png'],
imageUploadParam: 'image_param',
// Set the image upload URL.
imageUploadURL: urlPathConstants.imageUploadUrl,
// Set request type.
imageUploadMethod: 'POST',
toolbarButtons: {
moreText: {
buttons: ['bold', 'italic', 'underline', 'print', 'textColor', 'specialCharacters', 'subscript', 'superscript', 'strikeThrough', 'fontSize', 'backgroundColor'],
buttonsVisible: 5
},
moreParagraph: {
buttons: ['alignLeft', 'alignCenter', 'alignRight', 'alignJustify', 'formatOL', 'formatUL', 'paragraphFormat', 'outdent', 'indent', 'lineHeight'],
buttonsVisible: 5
},
moreRich: {
buttons: ['insertLink', 'insertImage', 'insertVideo', 'insertTable'],
buttonsVisible: 5
},
moreMisc: {
buttons: ['undo', 'redo', 'fullscreen', 'help' ],
align: 'right',
buttonsVisible: 2
}
},
colorsStep: 6,
colorsText: [
'#000000', '#ffffff', '#00377B', '#06B5CD', '#61C0CE', '#C2D0D7'
],
colorsBackground: [
'#000000', '#ffffff', '#00377B', '#06B5CD', '#61C0CE', '#C2D0D7', 'REMOVE',
],
tableStyles: {
noborder: 'Remove Border',
addborder: 'Add Border',
dashedborder: 'Dashed Border'
},
events: {
'image.beforeUpload': function (images) {
if (images.length) {
const uniqueId = newUniqueId;
const userId = loggedInUserId;
const image = images[0];
this.imageName = image.name;
this.imageSize = image.size;
this.imageType = image.type;
// Get the editor instance
// Set image upload parameters dynamically
this.opts.imageUploadParams = {
static_template_img_id: 0,
file_name: image.name,
temp_id: uniqueId,
page_no: 1,
file_size: image.size,
created_by: userId,
is_active: true,
};
console.log('Image Name:', image.name);
console.log('Image Size:', image.size);
console.log('Image Type:', image.type);
// Check if the image size exceeds the limit
if (image.size > 5 * 1024 * 1024) { // 5MB
alert('Image size exceeds the allowed limit of 5MB.');
return false; // Cancel the upload
}
// Check if the image type is allowed
if (!['image/jpeg', 'image/jpg', 'image/png'].includes(image.type)) {
alert('Invalid image type. Only JPEG and PNG are allowed.');
return false; // Cancel the upload
}
}
},
'image.uploaded': function (response) {
console.log('image.uploaded', response);
// Image was uploaded to the server.
},
'image.inserted': function ($img, response) {
console.log('image.inserted', $img, response);
// Image was inserted in the editor.
},
'image.replaced': function ($img, response) {
console.log('image.replaced', $img, response);
// Image was replaced in the editor.
},
'image.error': function (error, response) {
// Bad link.
if (error.code == 1) { console.log('Bad link.'); }
// No link in upload response.
else if (error.code == 2) { console.log('No link in upload response.'); }
// Error during image upload.
else if (error.code == 3) { console.log('Error during image upload.'); }
// Parsing response failed.
else if (error.code == 4) { console.log('Parsing response failed.'); }
// Image too text-large.
else if (error.code == 5) { console.log('Image too text-large.'); }
// Invalid image type.
else if (error.code == 6) { console.log('Invalid image type.'); }
// Image can be uploaded only to same domain in IE 8 and IE 9.
else if (error.code == 7) { console.log('Image can be uploaded only to same domain in IE 8 and IE 9.'); }
},
initialized: (editor) => {
setTimeout(() => {
this.registerCustomPrintButton(editor);
}, 5000);
const componentThis = this;
console.log(editor, 'initnlize')
this.setDefaultFont('editor_froala');
this.applyCustomFontToPastedContent('editor_froala');
this.editors[0] = editor;
if (this.templateData.page_list.length === 0) {
this.addPage();
} else {
this.templateData.page_list.forEach((pagedata) => {
this.addPage(pagedata);
});
}
if (this.templateData.page_list.length > 0) {
const lastPage = this.templateData.page_list[this.templateData.page_list.length - 1];
console.log(lastPage, 'lastPage')
this.editors[0]._editor.html.set(lastPage.static_content);
}
},
contentChanged: () => {
console.log('contentChanged')
if (this.isFileNameAndLanguageInvalid()) {
this.toastService.presentToast('File name and language cannot be empty', 4000, AppConstants.ERROR_SNACKBAR, 'top');
} else {
const currentContent = this.editors[0]._editor.html.get();
this.isUserTyping = true;
this.startTypingTimer(currentContent);
this.checkContentSize(currentContent);
}
}
}
};
}
====================================
private registerCustomPrintButton(editor) {
const component = this;
console.log('Registering print button for editor:', editor);
// Define the print command
FroalaEditor.RegisterCommand('print', {
title: 'Print',
callback: function (this: any) {
console.log('Print button clicked');
try {
const content = this.html.get();
console.log('Content to print:', content);
component.printContent(content);
} catch (error) {
console.error('Print failed:', error);
}
},
});
}
============================
printContent(contentToPrint: string) {
console.log(contentToPrint, 'contentToPrint');
const printWindow = window.open('', '_blank', 'height=600,width=800');
if (printWindow) {
// Include the application's stylesheet or inline critical styles
printWindow.document.write(`
<html>
<head>
<title>Print</title>
<link rel="stylesheet" href="styles.css"> <!-- Link to main stylesheet -->
<style>
body {
font-family: var(--font-NeueHaasDisplayLight);
font-size: 12pt;
margin: 20px;
}
</style>
</head>
<body>
${contentToPrint}
</body>
</html>
`);
printWindow.document.close();
printWindow.focus();
printWindow.print();
} else {
this.toastService.presentToast('Pop-up blocked. Please allow pop-ups to print.', 4000, 'error', 'top');
}
}
Any help is appreciated!