简体   繁体   中英

Print Div Content Using AngularJs

Inside AngularJs app, I want to inject generated content inside printDiv on certain on event. This printDiv is styled using and should be displayed on print only.

Below is the code snippet:

@media print {    
    body > #printDiv{
        display:block;
    }
    body > #screenContent{
        display:none;
    }        
}
@media screen {
    body > #printDiv {
        display: none;
    }
    body > #printContent{
        display:block;
    }
}

On certain event like ( ng-click ) like below example it calls function GenerateContent() on controller.

$scope.GenerateContent = function () {
   $("#divOne").text(data.FirstName);
   $("#divTwo").text(data.LastName);
   ...
     $scope.Print();
}

Here, I tried to fetch previously injected content using plain JS and then printed using window.print() like below:

$scope.Print = function () {
    var content = document.getElementById("printContent").innerHTML;            
    document.getElementById('printDiv').innerHTML = content;
    window.print();
}

And, finally on html page div structure is like below:

<html>
   <body>
       <div id="screenContent">
           // html content for screen only
       </div>
       <div id="printDiv"></div>
       <div id="printContent">
          <div id="divOne"></div>
          <div id="divTwo"></div>
       </div>
   </body>
</html>

On first attempt content is generated correctly and printed well. On every other attempt content is not injected, it always prints content generated on first attempt.

Is this correct way of injecting and printing div using AngularJs SPA? How can my example be fixed to work in expected manner?

Update:

I tried with ng-bind instead of using jquery like this

<div id="printContent" ng-controller="myController">
    <div id="divOne" ng-bind="firstName"></div>
    <div id="divTwo" ng-bind="lastName"></div>
</div>

and inside controller

$scope.firstName = data.FirstName;
$scope.lastName = data.LastName;

but this doesnt inject anything into dom.

I tried also with ng-model instead of ng-bind that also doesnt work.

Update 2

myController
(function () {
    "use strict";
    app.controller('myController',
       ....
        $http({
             method: 'POST',
             url: '/SomeService',
             data: ....,
           }).success(function (data) {
              $scope.firstName = data.FirstName;
              $scope.lastName = data.LastName;
          }
       });
    ...
}());

Update 3

<div id="printDiv">
   <div id="printContent" ng-app="myApp" ng-controller="myController">
      <div id="divOne" ng-bind="data.firstName"></div>
      <div id="divTwo" ng-bind="lastName"></div>
   </div>
</div>

myController code

angular.module('myApp', [])
.controller('myController', function ($scope) {
   $scope.firstName: "Bob";
   $scope.lastName: "Smith";
   window.print();
});

I'm calling window.print to print content inside printDiv where elements are binded to controller properties, yet this not working. When I look inside firebug content is not binded at all (html structure looks ok with ng-bing, but there is no actual content binded to that element).

What I'm doing wrong here?

Can't tell from your disconnected bits and pieces where you're going off track (where is GenerateContent located relative to everything else for example?) but here is a very simple example of a controller doing what you're asking for without jQuery:

DOM:

<div ng-app="foo">
     <div id="printContent" ng-controller="demoController">
        <div id="divOne" ng-bind="data.firstName"></div>
        <div id="divTwo" ng-bind="data.lastName"></div>
    </div>
</div>

Controller:

angular.module('foo', [])
    .controller('demoController', function ($scope) {
    $scope.data = {
        firstName: "Bob",
        lastName: "Smith"
    };

})

https://jsfiddle.net/m10ojexn/

So injecting content using jQuery in an angular app like this isn't going to work as Angular currently has no idea that things have changed and it needs to update the UI. The quick fix for this is using Angular's $timeout which is setTimeout that has been modified to work in conjunction with the Angular digest cycle. Any functions that use jQuery to update the UI should be wrapped in $timeout, like this:

$scope.GenerateContent = function () {
  $timeout(function () {
    $("#divOne").text(data.FirstName);
    $("#divTwo").text(data.LastName);
    ...
    $scope.Print();
  }, 0);
}

This should cause angular to evaluate your DOM updates. PS: Don't forget to inject $timeout into your controller.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM