Issue with UI Page/AngularJS and GlideDialogWindow

Matthew Glenn
Kilo Sage

Hey everyone,

Long story short, when I attempt to load a UI Page (w/AngularJS UI Script) in a GlideDialogWindow via a UI Macro, my AngularJS library is not being loaded. I did have a few relevant console errors yesterday but don't seem to be getting them today, but the problem still persists. I can only find one similar post on the community (AngularJS using GlideModal/GlideDialogWindow ). The errors outlined in that post are the exact errors I was receiving (minus the reference to the ngApp/ngController names).

Similar to the post mentioned above, if I go directly to the UI Page, everything loads just fine.

Has anyone seen this before? And more importantly, does anyone have a fix?

1 ACCEPTED SOLUTION

I'm with you on the iFrame hatred.   I was taking another look at this problem tonight and I came up with something that seems to work without iframe: manually bootstrapping angular.



Here is a simple example of an angular app in a UI Page or UI Macro.



<?xml version="1.0" encoding="utf-8" ?>


<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">


  <!--Note that ng-app is not used-->


  <div id="myAngularApp">


  <p>Input something in the input box:</p>


  <p>Name: <input type="text" ng-model="name"/></p>


  <p ng-bind="name"></p>


  </div>


  <g:requires name="angular.min.jsdbx" />


  <script>


  // You can add your modules like this and include them as a dependency when you call bootstrap


  angular


  .module('test', []);



  // Then you bootstrap by the div id instead of using ng-app


  angular.bootstrap($("myAngularApp"), ["test"]);


  </script>



</j:jelly>



This leads me to believe the issue is with the timing of the angular auto-initialization when it is loaded dynamically by GlideDialogWindow.


View solution in original post

13 REPLIES 13

tltoulson
Kilo Sage

Hi matthewsglenn,



I have been trying to isolate this issue for a while unsuccessfully but I have found a workaround: iFrames.   Here's the setup:



UI Page: Create your Angular App as a UI Page


UI Page 2: Create a second UI Page which has an iframe whose src attribute points to the first UI Page



GlideDialogWindow: Render UI Page 2 as a GlideDialogWindow




As far as I can tell, the problem occurs because Angular is being injected into an existing page by the GlideDialogWindow.   It seems to choke on this, whether its the dynamic insertion itself or something GlideDialogWindow is doing I haven't been able to tell.   The iFrame forces your Angular App to be rendered in a separate page while still being embedded as a popup.



I hope this helps.



Kind regards,



Travis


I was really excited that this got a reply until I saw the word 'iFrames'....     😕



Regardless, I've personally solved some odd issues using iFrames in the past so I don't see why it wouldn't do it this time around. I'll give it a try in the morning and let you know how it goes for me.



Thanks for the reply!


I'm with you on the iFrame hatred.   I was taking another look at this problem tonight and I came up with something that seems to work without iframe: manually bootstrapping angular.



Here is a simple example of an angular app in a UI Page or UI Macro.



<?xml version="1.0" encoding="utf-8" ?>


<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">


  <!--Note that ng-app is not used-->


  <div id="myAngularApp">


  <p>Input something in the input box:</p>


  <p>Name: <input type="text" ng-model="name"/></p>


  <p ng-bind="name"></p>


  </div>


  <g:requires name="angular.min.jsdbx" />


  <script>


  // You can add your modules like this and include them as a dependency when you call bootstrap


  angular


  .module('test', []);



  // Then you bootstrap by the div id instead of using ng-app


  angular.bootstrap($("myAngularApp"), ["test"]);


  </script>



</j:jelly>



This leads me to believe the issue is with the timing of the angular auto-initialization when it is loaded dynamically by GlideDialogWindow.


Holy moly. I've been banging my head on this all morning.... and afternoon. Thank you!!!


It all worked fine when testing it out in the UI Page, but as soon as I stuff it into the GlideDialogWindow, everything went to stuff.



I would like to add a couple things:


First, for UI Pages, I found you can put the full script in the "Client Script" section of the UI page. HTML is hard enough to read, might as well pull it out.



Second, to add other services, such as 'sn.glideAjax', you would add them to the Client Script as well, then include it in the array to the angular.bootstrap.



All together:


HTML:


<?xml version="1.0" encoding="utf-8" ?>  


<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">  


  <!--Note that ng-app is not used-->  


  <div id="AngularTestingApp">  


   


      <p>Input something in the input box:</p>  


      <p>Nameasfd: <input type="text" ng-model="name"/></p>  


      <p ng-bind="name"></p>  


    <div ng-controller="AngularTestingCtrl" >


   


      <p>   Random other variable here: {{myVariable}} </p>


    </div>


   


  </div>  


</j:jelly>  



Client Script:


// You can add your modules like this and include them as a dependency when you call bootstrap


angular


.module('AngularTestingModule', ['sn.glideAjax'])


.controller( 'AngularTestingCtrl', function($scope) {



  console.log( 'AngularTESTING. inside Ctrl' );



  $scope.myVariable = 'This value here';



});




angular.module('sn.glideAjax', []);


angular.module('sn.glideAjax').service('GlideAjax', function($rootScope) {


  var glideAjax = window.GlideAjax;


  glideAjax.prototype.getJSON = function(callback) {


  this.getXMLAnswer(function(answer) {


  var answerJSON = JSON.parse(answer);


  callback(answerJSON);


  $rootScope.$apply();


  });


  };



  return glideAjax;


});





// Then you bootstrap by the div id instead of using ng-app


angular.bootstrap($("AngularTestingApp"), ["AngularTestingModule", "sn.glideAjax"]);