5

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();
    };
}
vijayanand
  • 53
  • 1
  • 1
  • 5

1 Answers1

6

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)

Community
  • 1
  • 1
Omri Aharon
  • 16,959
  • 5
  • 40
  • 58
  • Thanks for your response, your fix was working for sample data. But we have a condition where we are doing some DOM manipulation to show or hide the DOM div’s based on the report type. JS fiddle here - http://jsfiddle.net/vijaivp/Y3BJa/309/ The detailed report does not get the updated result for printing. Can you check and let me know what would be the problem here. – vijayanand Mar 09 '15 at 13:26
  • @vijayanand This works : http://jsfiddle.net/Y3BJa/310/ You just needed to timeout the element selection since the function had to finish executing before the `ditems = newitems` change took place. – Omri Aharon Mar 09 '15 at 14:16
  • @vijayanand Glad to help. Just please for this answer and for future questions that you might ask, mark the answer as accepted so next users will know what helped you. (You mark accepted by checking the "tick" mark to the left of an answer) – Omri Aharon Mar 10 '15 at 12:41