I have a single page web application using angularJS. I need to print a div of certain page. I tried the following:
The page contains few div (print.html)
<div>
<div>
Do not print
</div>
<div id="printable">
Print this div
</div>
<button ng-click="printDiv('printableArea');">Print Div</button>
</div>
The controller has following script:
$scope.printDiv = function(divName) {
var printContents = document.getElementById(divName).innerHTML;
var originalContents = document.body.innerHTML;
document.body.innerHTML = printContents;
window.print();
document.body.innerHTML = originalContents;
}
This code prints the desired div but there is a problem.
the statement document.body.innerHTML = originalContents;
replaces the body of the whole application since it is a SPA. So when I refresh the page or click on print button again, the whole content of the page is erased.
This question is related to
javascript
angularjs
html
printing
single-page-application
I done this way:
$scope.printDiv = function (div) {
var docHead = document.head.outerHTML;
var printContents = document.getElementById(div).outerHTML;
var winAttr = "location=yes, statusbar=no, menubar=no, titlebar=no, toolbar=no,dependent=no, width=865, height=600, resizable=yes, screenX=200, screenY=200, personalbar=no, scrollbars=yes";
var newWin = window.open("", "_blank", winAttr);
var writeDoc = newWin.document;
writeDoc.open();
writeDoc.write('<!doctype html><html>' + docHead + '<body onLoad="window.print()">' + printContents + '</body></html>');
writeDoc.close();
newWin.focus();
}
This is what worked for me in Chrome and Firefox! This will open the little print window and close it automatically once you've clicked print.
var printContents = document.getElementById('div-id-selector').innerHTML;
var popupWin = window.open('', '_blank', 'width=800,height=800,scrollbars=no,menubar=no,toolbar=no,location=no,status=no,titlebar=no,top=50');
popupWin.window.focus();
popupWin.document.open();
popupWin.document.write('<!DOCTYPE html><html><head><title>TITLE OF THE PRINT OUT</title>'
+'<link rel="stylesheet" type="text/css" href="app/directory/file.css" />'
+'</head><body onload="window.print(); window.close();"><div>'
+ printContents + '</div></html>');
popupWin.document.close();
I don't think there's any need of writing this much big codes.
I've just installed angular-print bower package and all is set to go.
Just inject it in module and you're all set to go Use pre-built print directives & fun is that you can also hide some div if you don't want to print
http://angular-js.in/angularprint/
Mine is working awesome .
Two conditional functions are needed: one for Google Chrome, and a second for the remaining browsers.
$scope.printDiv = function (divName) {
var printContents = document.getElementById(divName).innerHTML;
if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
var popupWin = window.open('', '_blank', 'width=600,height=600,scrollbars=no,menubar=no,toolbar=no,location=no,status=no,titlebar=no');
popupWin.window.focus();
popupWin.document.write('<!DOCTYPE html><html><head>' +
'<link rel="stylesheet" type="text/css" href="style.css" />' +
'</head><body onload="window.print()"><div class="reward-body">' + printContents + '</div></body></html>');
popupWin.onbeforeunload = function (event) {
popupWin.close();
return '.\n';
};
popupWin.onabort = function (event) {
popupWin.document.close();
popupWin.close();
}
} else {
var popupWin = window.open('', '_blank', 'width=800,height=600');
popupWin.document.open();
popupWin.document.write('<html><head><link rel="stylesheet" type="text/css" href="style.css" /></head><body onload="window.print()">' + printContents + '</body></html>');
popupWin.document.close();
}
popupWin.document.close();
return true;
}
You can now use the library called angular-print
Okay i might have some even different approach.
I am aware that it won't suit everybody but nontheless someone might find it useful.
For those who do not want to pupup a new window, and like me, are concerned about css styles this is what i came up with:
I wrapped view of my app into additional container, which is being hidden when printing and there is additional container for what needs to be printed which is shown when is printing.
Below working example:
var app = angular.module('myApp', []);_x000D_
app.controller('myCtrl', function($scope) {_x000D_
_x000D_
$scope.people = [{_x000D_
"id" : "000",_x000D_
"name" : "alfred"_x000D_
},_x000D_
{_x000D_
"id" : "020",_x000D_
"name" : "robert"_x000D_
},_x000D_
{_x000D_
"id" : "200",_x000D_
"name" : "me"_x000D_
}];_x000D_
_x000D_
$scope.isPrinting = false;_x000D_
$scope.printElement = {};_x000D_
_x000D_
$scope.printDiv = function(e)_x000D_
{_x000D_
console.log(e);_x000D_
$scope.printElement = e;_x000D_
_x000D_
$scope.isPrinting = true;_x000D_
_x000D_
//does not seem to work without toimeouts_x000D_
setTimeout(function(){_x000D_
window.print();_x000D_
},50);_x000D_
_x000D_
setTimeout(function(){_x000D_
$scope.isPrinting = false;_x000D_
},50);_x000D_
_x000D_
_x000D_
};_x000D_
_x000D_
});
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>_x000D_
_x000D_
<div ng-app="myApp" ng-controller="myCtrl">_x000D_
_x000D_
<div ng-show="isPrinting">_x000D_
<p>Print me id: {{printElement.id}}</p>_x000D_
<p>Print me name: {{printElement.name}}</p>_x000D_
</div>_x000D_
_x000D_
<div ng-hide="isPrinting">_x000D_
<!-- your actual application code -->_x000D_
<div ng-repeat="person in people">_x000D_
<div ng-click="printDiv(person)">Print {{person.name}}</div>_x000D_
</div>_x000D_
</div>_x000D_
_x000D_
_x000D_
</div>_x000D_
_x000D_
Note that i am aware that this is not an elegant solution, and it has several drawbacks, but it has some ups as well:
Well, whoever you are reading this, have a nice day and keep coding :)
EDIT:
If it suits your situation you can actually use:
@media print { .noprint { display: none; } }
@media screen { .noscreen { visibility: hidden; position: absolute; } }
instead of angular booleans to select your printing and non printing content
EDIT:
Changed the screen css because it appears that display:none breaks printiing when printing first time after a page load/refresh.
visibility:hidden approach seem to be working so far.
Source: Stackoverflow.com