0

I have read several posts on this topic, but am still unable to get data loaded via ng-include to re-load after initially being loaded from a remote data server.

(Example How to reload / refresh model data from the server programmatically? )

I have a GSP page which renders a pull down menu of options, and when one is selected, ng-include calls a remote server and displays the data (in an ng-grid). Thus the ng-include needs the full path to the remote server in the URL. This code works correctly the first time an option is used, but will not re-load the data on subsequent selections. I understand that Angularjs is caching the data, but I need to force it to be re-loaded. Is there an event that I can catch inside "myTabController" to force it to call the ng-include? Is it possible to disable the cache? Since it is not possible to pass arguments from Angularjs into the URL of the ng-include, these parameters are being sent via AJAX calls in another section, so that the data server already has the parameters before the ng-include request is made.

_myTabs.gsp

<div ng-controller= "myTabController" ng-init="init(${selIds})">
<select name="tabSelect" ng-model= "tab" ng-options="t.name for t in tabs"></select>
<form name="tabForm">
  <div ng-switch="tab.value">
    <div ng-switch-when="optionA"<div ng-include="'https://datasrv:8453/DataApp/dataCtrl/aData'" ><div></div>
    <div ng-switch-when="optionB"<div ng-include="'https://datasrv:8453/DataApp/dataCtrl/bData'" ><div></div>
    <div ng-switch-when="optionC"<div ng-include="'https://datasrv:8453/DataApp/dataCtrl/cData'" ><div></div>
  </div>
</form>
</div>

myTabs.js

angular.module('myApp', ['ui.grid', 'ui.grid.resizeColumns', 'ngAnimate', 'ngRoute']);
app.controller("myTabController", function($scope, $interval, $filter, $window, $http, $rootScope, uiGridConstants){
$scope.tabs = {
  { name: '--- Please Select an Option ---', value: ' '},
  { name: 'A Label', value: 'optionA'},
  { name: 'B Label', value: 'optionB'},
  { name: 'C Label', value: 'optionC'}
 ];
}]);

Edit: From the replies to my question it appears that calling $templateCache.removeAll() could solve this problem. I can add an onload="xx()" to the ng-include, and a function to myTabController:

$scope.xx = function(){
  $templateCache.removeAll();
}

but of course it tells me that $templateCache is not defined. So I tried this inside of a run block:

$scope.xx = function(){
  app.run( function( $templateCache ){  
    $templateCache.removeAll();
  });
}

This did not generate an error, but it didn't do anything. The function xx() was being called, but it was not calling $templateCache.removeAll(). What am I missing?


Edit 2.

I tried using a directive to generate the ng-include tag:

    <div ng-switch-when="optionA"<div mydir ng-attr-path="https://datasrv:8453/DataApp/dataCtrl/aData" ><div></div>

In the directive, I tried adding a random number to the URL to make it unique:

.directive('mydir', ['$compile', function($compile){
  restrict: 'A',
  template: function( elem, attr ){
    var r = Math.random()
    var rpath = attr.path + '/?r=' + r
    return "<div ng-include=\"'" + rpath + "'\" onload=\""xx('" + rpath + "')\"></div>"; 
  }
};

Unfortunately this did not make any difference. It did generate the ng-include correctly, including the random string at the end. It displayed the data once, but the URL was never re-generated on subsequent calls. The xx() function was called every time it was loaded, however.

The key is to somehow force this directive to be called each time the menu item is selected, so the random number is called again to change the URL. Or use the xx() function to clear the cache. But how?


Edit 3: I see that there are problems with passing values using the "{{val}}" notation into a directive into the URL for an ng-include. Reference: modifying ng-include directive

Community
  • 1
  • 1
J21042
  • 1,214
  • 4
  • 19
  • 33
  • IDK if this answers your question, but there is a property on `$http` that allows you to tell it to not cache certain things. https://docs.angularjs.org/api/ng/service/$http From the link above: cache – {boolean|Cache} – If true, a default $http cache will be used to cache the GET request, otherwise if a cache instance built with $cacheFactory, this cache will be used for caching. Further, it might be better for you to put that in a directive to have more fine-grained control over how the whole thing works rather than using ng-include. – Pytth Dec 17 '15 at 18:06
  • Thanks, that looks promising, I see that $http is passed into myTabController, but its not clear to me how to use it. Maybe $http.defaults.cache = false; ? I will try it ... – J21042 Dec 17 '15 at 18:12
  • Or on your request do something like this: `$http.get('/api/users.json', { cache: true }).success(function(data){...}).error(function(data){...}) ` That being said, it sounds like you are still pretty early on in your learning of Angularjs. Depending on job requirements and what not, if this is just a personal project, you may want to look into using Angular 2 which officially dropped its beta yesterday. – Pytth Dec 17 '15 at 18:28
  • So just adding $http.defaults.cache = false; into myTabController did not seem to do anything. Pardon my ignorance of Angularjs, I am used to using straight GSP. I am not sure how to use $http.get in this case. One thing I did not mention is that the remote URL that is passed to the ng-include is actually being generated by the GSP. – J21042 Dec 17 '15 at 18:35
  • Did you try appending a ? and the current timestamp to the url, eg `https://datasrv:8453/DataApp/dataCtrl/bData?23453453456`? That helps busting caching. – Johannes Jander Dec 17 '15 at 18:42
  • That would work if I could re-generate the URL, but unfortunately the URL is generated by a GSP tag on the _myTabs.gsp view. So I can't use Angularjs to change it. – J21042 Dec 17 '15 at 19:14
  • Johannes, I tried using a directive to add a random string to the end of the URL, as mentioned in Edit#2, but it did not make any difference. It only generated the tag once. – J21042 Dec 18 '15 at 16:17

2 Answers2

0

First of all, all angular html when loaded go to $templateCahce, which you can manage manually, like:

  $templateCache.put('qwerty', 'pit is best'); 

then

<div ng-include="'qwerty'" ></div>

You can also remove anything from it using $templateCache.remove.

If you remove template, then angular will try to load new html from server. Now browser cache may come into play - to disable it you may want add something like ?timestamp= in http interceptor.

Note: your statement about ng-include seems weird to me - of course you can pass arguments to ng-include. And that's what you should do:

<div ng-include="myURL"> </div>

so u first do myURL = 'https://datasrv:8453/DataApp/dataCtrl/cData/selection=1' then myURL = 'https://datasrv:8453/DataApp/dataCtrl/cData/selection=2' and then you should not care about cache at all.

Petr Averyanov
  • 9,327
  • 3
  • 20
  • 38
  • I did not mention that the URL that is passed to the ng-include is actually generated by a custom GSP tag, so it has already been generated server side by the time Angularjs sees it. Selection parameters are passed to the remote server by separate AJAX calls outside of this menu. – J21042 Dec 17 '15 at 18:46
  • The actual GSP code looks like: and the GSP custom tag then generates the full ng-include code that I listed in the example. So I do not think there is a way to pass a param from Angularjs into the GSP tag. – J21042 Dec 17 '15 at 18:56
  • How can I call $templateCache.removeAll() from the controller? Can I just add $templateCache to the list of params passed in ? – J21042 Dec 17 '15 at 19:29
  • $templateCache is a usual service, you can inject it to any controller. If you generate this on server side - consider using not ng-include, but say custom-include="url" data-custom-include="smth_here"... – Petr Averyanov Dec 17 '15 at 20:59
  • Again, please pardon my ignorance, how do I inject $templateCache into the controller? When I tried adding $templateCache to the argument list in the controller "app.controller("myTabController", function($scope, ..., $templateCache), I got an error: "Template for directive 'uiGrid' must have exactly one root element" – J21042 Dec 17 '15 at 21:24
0

Once your template is loaded using ng-include and you want it to reload on button click or any link click then:-

Case 1:- Your template is already loaded in DOM. you only need to update your properties associated to the elements.

Case 2:- Use $scope.$broadcast to call the function which is mapped to the template. using $broadcast() you would be able to update you model/properties which is already associated to the DOM, and you template will be reloaded.

Shashikant Pandit
  • 2,752
  • 22
  • 29