3

There is a script, in my project, that loads through a http response. After I get response data I am separating the content and script using a directive and then displaying it into the front-end. My script is supposed to generate a graph. The problem is when I get the data from http that graph is not displaying. But if I use static data it will display the graph.

Also if I use an alert(), the graph is loading... I can't solve this issue.

Getting data from http:

.controller('AppController', ['$http', '$scope', '$templateCache', '$sce',
  function ($http, $scope, $templateCache, $sce) {
    $http.get("http://some url").success(function (data) {

         $scope.Value = data;
  });

Front-end display :

 <li ng-repeat="values in Value">  
    <bind-javascript html1="{{values.GENERATEDKPI}}"  ></bind-javascript>    
  </li>

separating content and executing the script:

   directive('bindJavascript', function ($sce,$timeout, $http) {
            return {
                restrict: 'E',
                scope: {
                    html1: '@'
                },
                template: '<div ng-bind-html="trustedHTML"></div>',
                replace: true,
                link: function (scope, element, attrs) {

                  scope.graphValue = scope.html1.split('~#~'); //separated the content and script 
                    scope.trustedHTML = $sce.trustAsHtml(scope.graphValue[0]);
                    if (scope.graphValue[1] != undefined) {
                        var script = angular.element(document.createElement('script'));

                            script[0].text = scope.graphValue[1];
                            angular.element(element).append(script[0]);

                        }

                }
            };
        });

Sample data : [{ "ASSIGNMENTID": null, "CUSTOMTITLE": null, "DISPTYPEID": "4", "GENERATEDKPI": "<div data-row=\"4\" data-col=\"1\" data-sizex=\"4\" data-sizey=\"3\" class=\"modal-content\"><header style=\"background-color: #457DC7\" class=\"Tooltip\" title=\"Idling Percentage: CustomTitle Test for Tooltip Plugin\"> Idling Percentage: CustomTitle Test for Tooltip Plugin <\/header>\u000d\u000a\u0009\u0009<div class=\"chartsdiv\">\u000d\u000a\u0009\u0009<div id=\"chart_div_1\"><\/div>\u000d\u000a\u0009\u0009<\/div>\u000d\u000a\u0009\u0009<div class=\"MoreInfoPanel scrollbar-inner\"><div class=\"KPISettings\"><table><tr><td class=\"caption\">Fleet:<\/td><td>All<\/td><\/tr><tr><td class=\"caption\">Vehicle:<\/td><td> E87349, N 14855, M 38068<\/td><\/tr>\u000d\u000a\u0009\u0009<tr><td class=\"caption\">Duration:<\/td><td>Last 24 Hours<\/td><\/tr><tr><td class=\"caption\">Range:<\/td><td>20 to 40 %<\/td><\/tr><\/table><\/div>\u0009\u0009\u000d\u000a\u0009\u0009<div class=\"scrollbar-inner scroll-sm\"><table class=\"griddata table table-hover table-responsive\"><thead><th>Vehicle<\/th><th>Value(%)<\/th><th>Status<\/th><\/thead><tbody><tr><td style=\"text-align:left;\">E87349<\/td><td>0.00 <\/td><td><img src=\"images\/kpi\/1_.png\" title=\"Safe\"><\/td><\/tr><tr><td style=\"text-align:left;\">N 14855<\/td><td>0.00 <\/td><td><img src=\"images\/kpi\/1_.png\" title=\"Safe\"><\/td><\/tr><tr><td style=\"text-align:left;\">M 38068<\/td><td>0.00 <\/td><td><img src=\"images\/kpi\/1_.png\" title=\"Safe\"><\/td><\/tr><\/tbody><\/table><\/div><\/div>\u000d\u000a\u0009\u0009<footer><a class=\"foo_moreinfo\">More Info<\/a><a><img src=\"..\/images\/icn-edit-kpi.png\" alt=\"\" title=\"Click here to Edit KPI\"><\/a>\u000d\u000a<a><img src=\"..\/images\/icn-remove-kpi.png\" alt=\"\" title=\"Click here to remove KPI\"><\/a><\/footer><\/div>\u000d\u000a\u0009~#~\u0009google.setOnLoadCallback(drawChart_1);function drawChart_1() {\u000d\u000a\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009var data = new google.visualization.arrayToDataTable([[\"Bands\", \"No.of.Vehicles\", { role: \"style\" }],[\"Safe\", 3, \"#04B713\"],[\"Warning\", 0, \"#FF7F00\"],[\"Critical\", 0, \"#FE0000\"],]);\u000d\u000a\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009var options = {width: 500,height: 400,colors: [\"Red\"],chartArea: { width: \"50%\" },hAxis: {title: \"KPI Status\",minValue: 0},vAxis: {title: \"No.of.Vehicles\",maxValue: 16,format: \"0\",gridlines: { count: 6 },minorGridlines: { count: 3 }}, legend: { position: \"none\" }};\u000d\u000a\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009var chart = new google.visualization.ColumnChart(document.getElementById(\"chart_div_1\"));chart.draw(data, options);}", "KPIId": "2", "Message": "Success", "REFRESHFREQUENCY": "3", "ResponseCode": "1" }, { "ASSIGNMENTID": null, "CUSTOMTITLE": null, "DISPTYPEID": "1", "GENERATEDKPI": "<div data-row=\"1\" data-col=\"4\" data-sizex=\"2\" data-sizey=\"1\" class=\"modal-content\"><header style=\"background-color: #457DC7\" class=\"Tooltip\" title=\"Idling Cost\"> Idling Cost <\/header>\u000d\u000a\u0009\u0009<div class=\"tilediv\"><table class=\"tiletable\"><tr><td colspan=\"2\"> 0.00\u000d\u000a <\/td><td rowspan=\"2\" colspan=\"2\" style=\"text-align: right\">\u000d\u000a <img src=\"images\/kpi\/img-safe-kpi.png \" \/><\/td><\/tr><tr>\u000d\u000a <td colspan=\"2\" class=\"unitcaption\"> INR <\/td><\/tr><\/table><\/div>\u000d\u000a\u0009\u0009<div class=\"MoreInfoPanel\"><div class=\"KPISettings scrollbar-inner\"><table><tr><td class=\"caption\">Fleet:<\/td><td>All<\/td><\/tr><tr><td class=\"caption\">Vehicle:<\/td><td>All<\/td><\/tr>\u000d\u000a\u0009\u0009<tr><td class=\"caption\">Duration:<\/td><td>Last 1 Week<\/td><\/tr><tr><td class=\"caption\">Range:<\/td><td>9,000.00 to 10,000.00 INR<\/td><\/tr><\/table><\/div>\u0009\u0009\u000d\u000a\u0009\u0009<div class=\"scrollbar-inner scroll-sm\"><table class=\"griddata table table-hover table-responsive\"><thead><th>Vehicle<\/th><th>Value(INR)<\/th><th>Status<\/th><\/thead><tbody><tr><td style=\"text-align:left;\">E87349<\/td><td>0.00 <\/td><td><img src=\"images\/kpi\/1_.png\" title=\"Safe\"><\/td><\/tr><tr><td style=\"text-align:left;\">D47843<\/td><td>0.00 <\/td><td><img src=\"images\/kpi\/1_.png\" title=\"Safe\"><\/td><\/tr><tr><td style=\"text-align:left;\">N 14855<\/td><td>0.00 <\/td><td><img src=\"images\/kpi\/1_.png\" title=\"Safe\"><\/td><\/tr><tr><td style=\"text-align:left;\">M 38068<\/td><td>0.00 <\/td><td><img src=\"images\/kpi\/1_.png\" title=\"Safe\"><\/td><\/tr><tr><td style=\"text-align:left;\">M 38069<\/td><td>0.00 <\/td><td><img src=\"images\/kpi\/1_.png\" title=\"Safe\"><\/td><\/tr><tr><td style=\"text-align:left;\">ADT_veh_20<\/td><td>0.00 <\/td><td><img src=\"images\/kpi\/1_.png\" title=\"Safe\"><\/td><\/tr><tr><td style=\"text-align:left;\">B99506<\/td><td>0.00 <\/td><td><img src=\"images\/kpi\/1_.png\" title=\"Safe\"><\/td><\/tr><tr><td style=\"text-align:left;\">P 51993<\/td><td>0.00 <\/td><td><img src=\"images\/kpi\/1_.png\" title=\"Safe\"><\/td><\/tr><\/tbody><\/table><\/div><\/div>\u000d\u000a\u0009\u0009<footer><a class=\"foo_moreinfo\">More Info<\/a><a><img src=\"images\/kpi\/icn-edit-kpi.png\" alt=\"\" title=\"Click here to Edit KPI\"><\/a>\u000d\u000a\u0009\u0009<a><img src=\"images\/kpi\/icn-remove-kpi.png\" alt=\"\" title=\"Click here to remove KPI\"><\/a><\/footer><\/div>", "KPIId": "10", "Message": "Success", "REFRESHFREQUENCY": "1", "ResponseCode": "1" }]

6
  • the problem seems to be that the http request is not getting resolved on time you can solve that using promises check this answers here stackoverflow.com/questions/37853439/… Commented Jun 20, 2016 at 14:40
  • 1
    Personally I think sending script with http call is little awkward. Commented Jun 20, 2016 at 15:10
  • Is your sample data the actual response to the $http.get() or the static text you see executing successfully or both? When you say that it works when you use "static data" what do you mean? Do you simply include it in your html? Your javascript? Commented Jun 20, 2016 at 19:16
  • @tokkov If i just assign the static data into the outside of the http function, Ex: $http.get("some url").success(function (data) { $scope.Value = data; //Its not working }); $scope.Value = 'sample data'; //Its working Commented Jun 21, 2016 at 4:37
  • ng-repeat is looking for an array and failing to find one it will separate the string into individual character and loop over them. Can you provide a sample of the exact response to your $http.get()? Because the structure of that response may be part of the issue. Commented Jun 21, 2016 at 12:42

2 Answers 2

0

Dido use promise so that you make sure data is not null before returning it. why won't you try to

  .controller('AppController', ['$http', '$scope', '$templateCache', '$sce', '$q' , 
  function ($http, $scope, $templateCache, $sce, $q) {
    deferred = $q.defer()
    $http.get("http://some url").success(function (data) {
         deferred.resolve(data)
         return deferred.promise
  });

Or maybe test if Value exists ( or not yet ) , before entering to the directive. to do so try ;

<li ng-repeat="values in Value" ng-if"Value">  
    <bind-javascript html1="{{values.value}}"  ></bind-javascript>    
</li>

Hope it helps

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your answer but it is not loading the script (not generating the graph).
0

I've gotten this (mostly) working here using a copy of your modified data. The only real change I made was to alter the {{values.value}} to the one you indicated you would use. I also note that your second array element actually lacks the ~#~ character sequence you are trying to split on, so that one just returns a single element array and the call to scope.graphValue[1]; returns undefined.

I don't know what pieces you might have that aren't posted that could contribute to the issue you are seeing but based on what you did provide it should work by simply calling the proper attribute on the element of the $scope.Value array in your ng-repeat.

I don't have your graph dependencies in my test but if you run it on your own you will see that it does try to execute the javascript your web service returns and in my case gets an "Uncaught ReferenceError: google is not defined". Are you seeing that error or no? Either way that goes there are different things to try next. If google is not defined then your script is not able to access other resources you have already prepped in your app but may be out of scope for that script. If you do not see that error then make sure that you are injecting it into your app properly.

Edit: I just added a small change to your directive template that may make all the difference for you. Wrapping your directive template in a placeholder <div></div> allows angular to inject the <script></script> tag inside your directive properly. This is normal behavior with directives that have replace: true on them since angular requires them to have a single root element and appending your script tag would violate that. It still doesn't explain why you see it working at all, but it is a change to my plunkr that lets it successfully inject the scripts into the page.

Edit 2: Ok, I am not going to say that this is the best answer. In fact I am going to say it is really a pretty poor answer, but it does show at least one way to work around the issue with the delay involved while the promises resolve. I have updated the plunker to show the solution and hope it is a good starting point for you to get your graphs working. Note that I did have to add a third section to your json response adding the callback method name at the end of your string with ~#~functionName. You would probably be better off making each piece a separate attribute of your response's json object just for efficiency (avoiding using split()) but that is up to you.

I was also wondering if you had looked at angular-google-chart to perhaps avoid this issue entirely? It seems to encapsulate the javascript chart binding into a directive itself that may avoid this problem entirely. I was going to try it out with your code but plunker seems to be unable to find it for inclusion when I try.

6 Comments

Thank you for the answer, I have added the graph related scripts in the link plnkr.co/edit/vPWvmpClwyoCfrrE2eUp?p=preview
And also see this link also plnkr.co/edit/VhcYdUj0rm6A5o6Rhiwa?p=preview, I have specified the data in the outside of the http function so its generating the graph, Bit its not working when i get the data from the http response.
Very interesting. When I put the full JSON into the hard coded side, it runs properly. But as soon as it comes back in the $http call it refuses to run the javascript. The script tag is added but does not execute. I can break your code by moving the assignment of $scope.Value inside the $http.success function. When it is set with the promise then hard coding it fails too. So the issue is around promises. I will dig further to see what I can come up with. You may need to add a watch to the directive so angular is looking for the script tag to be added and ensures it is processed.
Yes, You are exactly correct, I am struggling with same issue can't find the solution.
Ok, I have a rather ugly starting point for you and have edited the answer with an example of it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.