0

Working on a reporting application where reports are generated (in HTML) from a BIRT Report Engine object. The report data comes as a JSON string is recieved from XHR. The JSON string contains a combination of HTML and javascript (a function call, specifically). Once received, the report data is stuffed into a for display in the view. The view is put together using AngularJS.

I did some research and found that binding the HTML/javascript to the view in Angular requires the use of $compile. Using that as a basis, i put together some code that will include data and execute code bound from a string defined explicitly in the $scope. But - unless i'm going overlooking something after staring at the same stuff for a couple hours, the approach i'm using does not work with $scope data defined by XHR. Here's a plunkr to show the general idea implemented. Any suggestions would be greatly appreciated.

The HTML

<!DOCTYPE html>
<html data-ng-app="example">
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.11.0/ui-bootstrap-tpls.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular-sanitize.js"></script>
    <script src="script.js"></script>
</head>
<body ng-controller="controller" >
    <h1>Static Content</h1>
    <p><button href="javascript: void(null)" role="link" ng-click="loadSubreport('recv_po_detail.rptdesign', 'static')">PO000007</button></p>
    <h1>HTML from static string</h1>
    <div compile="snippet"></div>
    <h1>HTML from server string</h1>
    <div compile="html.body"></div>
    <hr />
    <button ng-click="alert()">Show XHR Data</button>
</body>
</html>

The Javascript

    var app = angular.module('example', []);
    app.controller('controller', ['$scope', '$compile', '$http', function ($scope, $compile, $http){
        $scope.snippet="<p><button href=\"javascript: void(null)\" ng-click=\"loadSubreport('recv_po_detail.rptdesign', 'compiled')\">PO000007</button></p>";
        $http.get('data.json')
                .success(function (data) {
                    $scope.html = data;
                });
        $scope.loadSubreport = function (filename, source) {
            alert("Called from " + source);
        };
        $scope.alert = function () {{
          alert($scope.html.body);
        }}
    }]);
    app.directive('compile', ['$compile', function ($compile) {
                "use strict";
                return function (scope, element, attrs) {
                    var ensureCompileRunsOnce = scope.$watch(
                            function (scope) {
                                return scope.$eval(attrs.compile);
                            },
                            function (value) {
                                element.html(value);
                                $compile(element.contents())(scope);
                                ensureCompileRunsOnce();
                            }
                    );
                };
            }]);
Community
  • 1
  • 1
The Head Rush
  • 3,157
  • 2
  • 25
  • 45

1 Answers1

0

Your watch goes off right at the start, when html.body still is undefined. Then you run ensureCompileRunsOnce() and unwatch the scope. So the proper report, once loaded, never gets compiled. I uncommented the line ensureCompileRunsOnce() and get a nice view of the report.

DEMO

flup
  • 26,937
  • 7
  • 52
  • 74