1

I am using ng-src in <img> tag, but whenever I am changing the ng-src on clicking the next or previous button, it loads the image in the browser (checked in network tab), although all the images are already loaded. So clicking on the next or previous button does not give a smooth experience and image firstly downloaded again by the browser and then rendered.

Can someone help me to solve this issue so that images which are already loaded by browser need not be loaded by making a new HTTP request.

<div class="slider" ng-style="{'width': ctrl.options.width,'height':ctrl.options.height}">
    <img class="materialboxed mainImage"
         ng-style="{'width': ctrl.options.width,'height':ctrl.options.height}"
         ng-src="{{ctrl.data[ctrl.currentImageIndex]}}">
    <i class="material-icons icon-arrow_left"
       ng-if="ctrl.displayLeftArrow"
       ng-click="ctrl.prevImg()">keyboard_arrow_left
    </i>
    <i class="material-icons icon-arrow_right"
       ng-if="ctrl.displayRightArrow"
       ng-click="ctrl.nextImg()">keyboard_arrow_right
    </i>
</div>

Here is the array of images that I am using:

[
        'https://static.pexels.com/photos/257360/pexels-photo-257360.jpeg',
        'https://lorempixel.com/580/250/nature/1',
        'https://lorempixel.com/580/250/nature/2',
        'https://lorempixel.com/580/250/nature/3',
        'https://lorempixel.com/580/250/nature/4',
    ]

Controller is here:

    preloader.preloadImages($scope.data);

    self.init = function () {
        self.currentImageIndex = 0;
        checkArrowVisibility();
    };

    self.prevImg = function () {
        self.currentImageIndex--;
        checkArrowVisibility();
    };
    self.nextImg = function () {
        self.currentImageIndex++;
        checkArrowVisibility();
    };

$scope.data holds the images array

4
  • 1
    how do you load them? post the function or the controller Commented Dec 16, 2017 at 8:17
  • 1
    @svarog updated description Commented Dec 16, 2017 at 8:45
  • What does checkArrowVisibility() do? Commented Dec 16, 2017 at 8:51
  • checks if left and right arrow are to be visible, that's not much related to my problem, you can skip. You should check prevImg() and nextImg() Commented Dec 16, 2017 at 8:53

2 Answers 2

1

if you are using through $http service you can enable the cache by setting the cache parameter as true:

$http({
   method: 'GET',
   url: '/api/images',
   cache: true
});

otherwise use '$cacheFactory'to manually cache the data.

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

2 Comments

I don't have any API, user gives me array of imageUrls and I just use it in ng-src of image tag
@VarunSukheja then you can use angular build in cache factory
0

As far as I can see, you preload all images upfront with preloader.preloadImages($scope.data);. In this case it is much easier not to put effort in to doing it programmatically, but just let the browser do it's job. To achieve this, I propose to put all images of slider into the DOM and just show/hide them on demand instead of setting different src (that is what actually triggers reload of the image again and again).

The essential part here would be <img ng-src="{{img}}" ng-repeat="img in ctrl.data" ng-show="$index === ctrl.cur" ...>. Pay attention that you should use ng-show and not ng-if here! Also you can utilize $index added by ng-repeat, which is quite handy in this case.

angular.module('app', []).controller('ctrl', function() {
  this.cur = 0;
  this.data = [
    'https://static.pexels.com/photos/257360/pexels-photo-257360.jpeg',
    'https://lorempixel.com/580/250/nature/1/',
    'https://lorempixel.com/580/250/nature/2/',
    'https://lorempixel.com/580/250/nature/3/',
    'https://lorempixel.com/580/250/nature/4/'
  ];
  this.width = 'auto';
  this.height = '250px'
})
<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script data-require="[email protected]" data-semver="1.6.5" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-controller="ctrl as ctrl">
    <h1>Slider</h1>
    <div>
      <img ng-src="{{img}}" ng-repeat="img in ctrl.data" ng-show="$index === ctrl.cur" alt="Image #{{$index}}" ng-style="{'width':ctrl.width, 'height': ctrl.height}"/>
      <br/>
      <button ng-click="ctrl.cur = ctrl.cur - 1" ng-show="ctrl.cur > 0">Previous</button>
      <button ng-click="ctrl.cur = ctrl.cur + 1" ng-show="ctrl.cur < ctrl.data.length - 1">Next</button>
    </div>
  </body>

</html>

Plunker: https://plnkr.co/edit/Mz9fo2MgcA36DYhQ8uRj?p=preview

You can see in the network tab of dev tools that images are loaded only once.

Comments

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.