Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Angular to create n printable pages?

Well, I've searched a bit and did not find anything similar.

I want to know how can I use Angular to create printable content, jump to the end of the page and print more content.

How can I force the content to always fit on a specific size, like a PDF? Do I need Angular to do this? If not HTML, can I iterate over PDF printable pages?

Example:

Suppose I'm a teacher and I've asked my students to send a 10 lines essays to a specific web system. Now, in the admin page, I want to print 10 students essays on 10 pages, every one of them starting on line 0 of the respective page.

Example 2:

Suppose I want to print n blank pages. On a system, I'm asked how many pages do I want and Angular prints it.

Example 3:

Suppose I have an array with 3 names. I want to print the first name on the first page, second on the second and third on the third.

@edit

This is the final project implemented. It's a timeSheet generator. It takes an array inside app.js and print a new page for every employee.

like image 681
Rodmentou Avatar asked Dec 09 '22 01:12

Rodmentou


2 Answers

I wanted to put this as a comment, but I don't have enough rep so please excuse me. :/

Maybe not a direct answer, but I suggest you also take a look at this directive I found some time ago:

This directive lets you isolate specific parts of your page for printing.

app.directive('ngPrint', function () {
    var printSection = document.getElementById('printSection');
    // if there is no printing section, create one
    if(!printSection) {
        printSection = document.createElement('div');
        printSection.id = 'printSection';
        document.body.appendChild(printSection);
    }

    function link(scope, element, attrs) {
        element.on('click', function () {
            printSection.innerHTML = '';
            var elemToPrint = document.getElementById(attrs.printElementId);
            if(elemToPrint) {
                printElement(elemToPrint);
            }
        });
        window.onafterprint = function () {
            // clean the print section before adding new content
            printSection.innerHTML = '';
        }
    }

    function printElement(elem) {
        // clones the element you want to print
        var domClone = elem.cloneNode(true);
        printSection.appendChild(domClone);
        window.print();
    }
    return {
        link: link,
        restrict: 'A'
    };
});

You can define what id of element this directive will work on by specifying the print-element-id attribute, like so:

<button ng-print print-element-id="printThis">Print</button>

And you define the printable area by using the same id, like this:

<div id="printThis">
    <!--insert printable content here.-->
</div>

This clones all contents of the element with id of printThis into an element with id of printSection, which is appended at the end of the document. What's left to do is to hide printSection when you're not printing, and show only the printSection, hide everything else when you are. The only other thing to remember is to include styles for printing. Mine looked like this:

@media screen {
    #printSection {
        display: none;
    }
}
@media print {
    body * {
        display:none;
        visibility:hidden;
    }

    #printSection, #printSection *:not(table):not(thead):not(tbody):not(tr):not(td):not(th){
        display: block;
        visibility:visible;
    }
    #printSection {
        position:absolute;
        left:0;
        top:0;
        margin-bottom:0;
    }
    table{
        display:table;
        visibility:visible;
    }
    thead{
        display:table-header-group;
        visibility:visible;
    }
    tbody{
        display:table-row-group;
        visibility:visible;
    }
    td, th{
        display:table-cell;
        visibility:visible;
    }
    tr{
        display:table-row;
        visibility:visible;
    }

}

I used this in an app I've been developing, where the dashboard and UI components were interfering with the printability of the contents I wanted to print.

Credit goes to this article. I've since modified the directive, but I never would've done it without reading it.


As an added comment, I think what you're trying to accomplish is something out of Angular's capabilities. You can print up to n items or articles, but there's no easy way to define them as pages inside the Angular app itself. What I suggest is to use @zeroflagL's answer in conjunction with this directive.

<div id="printThis">
    <p ng-repeat="essay in essays" class="pageBreak>
      {{essay}}
    </p>
</div>

My two cents.

like image 31
Ralph Sto. Domingo Avatar answered Dec 10 '22 14:12

Ralph Sto. Domingo


You simply apply the appropriate CSS:

.pageBreak {
  page-break-after: always;
}


<p ng-repeat="essay in essays" class="pageBreak">
{{essay}}
</p>

Every essay will be printed on a separate page.

like image 104
a better oliver Avatar answered Dec 10 '22 15:12

a better oliver