最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to remove angular $modal cache? - Stack Overflow

programmeradmin7浏览0评论

In my angular app I have multiple of $modal instances which are created like:

var modalInstance = $modal.open({
        templateUrl: APP_CONFIG.TPL_PATH + '/path/template.html',
        controller: 'TemplateController'//...
});

The problem is that after viewing these modals they are cached, and if I change them, I'm forced to clear the browsers cache. Not a problem on dev machine, but an issue, when I will provide this app to potential users.

I've found these as "solutions" so far:

// first one
$rootScope.$on('$stateChangeStart', function(event, next, current) {
    $templateCache.remove(current.templateUrl);
}); // doesn't work because $modal doesn't change state

// second one
$rootScope.$on('$viewContentLoaded', function() {
    $templateCache.removeAll();
}); // mess Bootstrap UI which adds default partials directly to the $templateCache

// third one
$modal.open({
            templateUrl: '/app/ponents/your-modal.html?bust=' + Math.random().toString(36).slice(2),
            controller: 'YourModalController'
        }); // ugly and inefficient - I have to change multiple code blocks for every modal

Are there any sufficient solutions? Thank you in advance.

EDIT

An extra advice I got is changing template data and putting it into .js files (i.e <p>Data</p> to <p>{{data}}</p> and $scope.data = 'Data' in .js). Two problems I see here. How can I be sure that the .js file isn't cached by browser? How can I add extra changes to template structure (extra variables), if it's cached (i.e to <p>{{data}}</p><img src='{{imageUrl}}>')?

In my angular app I have multiple of $modal instances which are created like:

var modalInstance = $modal.open({
        templateUrl: APP_CONFIG.TPL_PATH + '/path/template.html',
        controller: 'TemplateController'//...
});

The problem is that after viewing these modals they are cached, and if I change them, I'm forced to clear the browsers cache. Not a problem on dev machine, but an issue, when I will provide this app to potential users.

I've found these as "solutions" so far:

// first one
$rootScope.$on('$stateChangeStart', function(event, next, current) {
    $templateCache.remove(current.templateUrl);
}); // doesn't work because $modal doesn't change state

// second one
$rootScope.$on('$viewContentLoaded', function() {
    $templateCache.removeAll();
}); // mess Bootstrap UI which adds default partials directly to the $templateCache

// third one
$modal.open({
            templateUrl: '/app/ponents/your-modal.html?bust=' + Math.random().toString(36).slice(2),
            controller: 'YourModalController'
        }); // ugly and inefficient - I have to change multiple code blocks for every modal

Are there any sufficient solutions? Thank you in advance.

EDIT

An extra advice I got is changing template data and putting it into .js files (i.e <p>Data</p> to <p>{{data}}</p> and $scope.data = 'Data' in .js). Two problems I see here. How can I be sure that the .js file isn't cached by browser? How can I add extra changes to template structure (extra variables), if it's cached (i.e to <p>{{data}}</p><img src='{{imageUrl}}>')?

Share Improve this question edited Dec 18, 2015 at 16:48 Georgy asked Dec 18, 2015 at 11:50 GeorgyGeorgy 2,4623 gold badges22 silver badges35 bronze badges 3
  • Are you dynamically creating the template.html file? – Malkus Commented Dec 18, 2015 at 12:02
  • @Malkus Depends on what you mean. I have stored htmls, but use angular to bind to data and display inputs (for example) with data from server (through $http.post). In general modals provide access to CRUD operations. – Georgy Commented Dec 18, 2015 at 12:09
  • Unfortunately, it is unclear what you are asking. Take a look at how you are structuring your files and what you are trying to acplish and find a more angular way to solve your problem. – Malkus Commented Dec 18, 2015 at 16:25
Add a ment  | 

4 Answers 4

Reset to default 4

Well, when we speak about 'sufficient' it's the matter of taste and particular problem, but I did find this answer to be quite satisfying:

You can't delete browser's cache directly with JavaScript. This is due to security demand. And it's a bit wrong to do this - lots of smart developers know better what to store and what to delete. But there is a simple trick: using of ?keyword=hash. Even if the pages you see would be similar, if there are different hashes for them, then browser will store two versions of the pages. Adding ?keyword=hash in every $model.open() is annoying and unprofessional (DRY, KISS). Let's use angular interceptors then.

yourApp.factory('HttpInterceptor', function($templateCache, APP_CONFIG) {
  return {
    'request': function(request) {
      if (request.method === 'GET' && $templateCache.get(request.url) === undefined) {
        request.url += '?ver=' + APP_CONFIG.VERSION;
      }
      return request;
    }
  };
});

Put it into $httpProvider.interceptors:

$httpProvider.interceptors.push('HttpInterceptor');

Now you can specify version number (take it from your repo, for instance, or include timestamps). The version is changed - browser loads the new version of your templates. The if $templateCache.get(request.url) === undefined condition is used for filtering requests for precached (automatically injected maybe) content. Interceptors idea is taken from here: https://stackoverflow./a/25060769/4753661 .

A short summary about your options provided

The first and second options:

// first one
$rootScope.$on('$stateChangeStart', function(event, next, current) {
    $templateCache.remove(current.templateUrl);
}); // doesn't work because $modal doesn't change state

// second one
$rootScope.$on('$viewContentLoaded', function() {
    $templateCache.removeAll();
}); // mess Bootstrap UI which adds default partials directly to the $templateCache

You defenitly do not want to be arbitrarily clearing items from $templateCache which seems like what your first two options where doing. Angular would then have to reAdd views to the templateCache over and over again.

The third option:

$modal.open({
            templateUrl: '/app/ponents/your-modal.html?bust=' + Math.random().toString(36).slice(2),
            controller: 'YourModalController'
        }); // ugly and inefficient - I have to change multiple code blocks for every modal

This would actually create a memory leak because you would now have an infinite number of templates being added to the $templateCache.

Better Solutions

My Remended Answer

I would remend renaming your template.html file to have unique identifiable names.

i.e. modalTemplate_alertModal.html, modalTemplate_newEmployeeModal.html...

Then you get to actually leverage the benefits of the $templateCache and improve performance.

If you absolutely cannot rename the template.html files.

In this case you can clear the specific template from the templateCache before you open the modal.

//Get TemplateURL
var TemplateURL = APP_CONFIG.TPL_PATH + '/path/template.html';

//Remove Cached ModalTemplate
$templateCache.remove(TemplateURL);

//Open Modal
var modalInstance = $modal.open({
        templateUrl: TemplateURL,
        controller: 'TemplateController'//...
});

I can have a static header (i.e. <h2>Create new entry</h2>). And then to change it (_<h2>Create new user entry</h2>). If I had previously viewed the modal, I wouldn't get the updated header without clearing cache.

Based on this statement what you really want to be doing is using the controller and $scope to update these values.

<h2>{{modalHeader}}</h2>

Then wherever you are defining what the header needs to be update he value

$scope.modalHeader = "Create new user entry";

Keep in mind angularjs piles and manages the DOM the only way to properly change DOM values is using directives.

add the following section to your webconfig. You will need to clear your current browser cache manually, but going foward a page reload will work,

  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Cache-Control" value="no-cache, no-store, must-revalidate" />
        <add name="Pragma" value="no-cache" />
        <add name="Expires" value="0" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
发布评论

评论列表(0)

  1. 暂无评论