Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

$window.print(), does not print the updated model data in angular js

I have a table with some data to view in html. when i do click print, i need to get all the data from db and print it. I am getting the data and populating the model data when i click on print, only the model is updated and print shows the old data. In the code below, newitems is not added to items when i click on print.

http://jsfiddle.net/vijaivp/Y3BJa/306/

HTML

<div ng-app>
    <div class="hidden-print" ng-controller="PrintCtrl">
        <br />
        <div id="overallPrint" class='visible-print' style="float:left;     margin-right:50px;">
            <h4>Overall Report</h4>

            <table border="1">
                <thead>
                    <tr>
                        <td>Name</td>
                        <td>Price</td>
                        <td>Quantity</td> 
                    </tr>
                </thead>
                <tbody>
                    <tr ng-repeat="item in items">
                        <td>{{item.Name}}</td>
                        <td>{{item.Price}}</td>
                        <td>{{item.Quantity}}</td>                       
                    </tr>
                </tbody>
            </table>

            <br>
            <input type="button" value="Print Overall" ng-click='printOverallReport()' />
        </div>
    </div>
</div>

JS

function PrintCtrl($scope, $window, $q)  {
    $scope.items = [

        {Name: "Soap", Price: "25", Quantity: "10"},
        {Name: "Shaving cream", Price: "50", Quantity: "15"}
    ];

    $scope.newitems = [
        {Name: "Shampoo", Price: "100", Quantity: "5"}
    ];

    $scope.printOverallReport = function () {
        $scope.items.push($scope.newitems[0]);
        $window.print();
    };
}
like image 791
vijayanand Avatar asked Mar 06 '15 11:03

vijayanand


1 Answers

Using a timeout with Angular's $timeout service will fix it:

function PrintCtrl($scope, $window, $q, $timeout)  {
        $scope.items = [
        
            {Name: "Soap", Price: "25", Quantity: "10"},
            {Name: "Shaving cream", Price: "50", Quantity: "15"}
        ];
    
        $scope.newitems = [
            {Name: "Shampoo", Price: "100", Quantity: "5"}
        ];

    $scope.printOverallReport = function () {
        $scope.items = $scope.newitems;
        console.log($scope.items.length);
        $timeout($window.print, 0);
        console.log($scope.items.length);
      };
    
}

Fiddle

For a comprehensive explanation as to why, please see DVK's answer (2nd one) here: Why is setTimeout(fn, 0) sometimes useful?

TL:DR;

When you call $window.print() the old HTML is still present since the browser hasn't rendered it yet. It's waiting to finish the javascript function run. setting a $timeout 0 will queue the print at the end of execution queue and will guarantee it happens after the HTML has been rendered. (I still strongly recommend to read his answer)

like image 198
Omri Aharon Avatar answered Oct 07 '22 00:10

Omri Aharon