5

I need to display an image in its actual size, even if it is bigger than its container. I tried the trick of using Image variable and capturing the size on load with something like this:

HTML:

<div ng-controller="MyCtrl">
    <input ng-model="imageurl" type="url" />
    <button ng-click="loadimage()" type="button">Load Image</button>
    <img ng-src="{{image.path}}"
        style="width: {{image.width}}px; height: {{image.height}}px" />
</div>

Javascript:

.controller("MyCtrl", ["$scope", function ($scope) {
    $scope.image = {
        path: "",
        width: 0,
        height: 0
    }
    $scope.loadimage = function () {
        var img = new Image();
        img.onload = function () {
            $scope.image.width = img.width;
            $scope.image.height = img.height;
            $scope.image.path = $scope.imageurl;
        }
        img.src = $scope.imageurl;
    }
}]);

This script works, but only after the button is clicked several times if the image is big.

What should I do to make it work in one click?

Is there a better way to discover the image size than this?

Community
  • 1
  • 1
Endy Tjahjono
  • 22,572
  • 20
  • 76
  • 111
  • 3
    Move the code to a directive - DO NOT try to call the onload function inside the controller - Read the best practices here: http://docs.angularjs.org/misc/faq#dommanipulation – callmekatootie Jun 10 '13 at 07:54
  • @callmekatootie Can you elaborate? Why moving the onload to a directive is better? – Endy Tjahjono Jun 10 '13 at 10:15

3 Answers3

6

You need to use $scope.$apply, otherwise any changes to $scope made in non-Angular event handlers won't be processed properly:

img.onload = function () {
  $scope.$apply(function() {
    $scope.image.width = img.width;
    $scope.image.height = img.height;
    $scope.image.path = $scope.imageurl;
  });
}
robertklep
  • 174,329
  • 29
  • 336
  • 330
  • Thanks! I found that if I put `$scope.$apply();` after `$scope.image.path = $scope.imageurl;`, the image is also loaded. Which is better? – Endy Tjahjono Jun 10 '13 at 07:33
  • @EndyTjahjono good question, I don't know if one is preferable over the other :) – robertklep Jun 10 '13 at 07:41
  • 1
    According to [this article](http://jimhoskins.com/2012/12/17/angularjs-and-apply.html) it is better to use your format because it will use angular's built in error handling mechanism. – Endy Tjahjono Jun 10 '13 at 09:34
2

May be it is still not late to re-build whole thing according to directives "pattern". My solution for similar problem ( link ) got several up-votes and it causes me to think that it is conventional approach.. Have a look:

HTML:
    <div ng-controller="MyCtrl">
        <input ng-model="image.tmp_path" type="url" />
        <button ng-click="loadimage()" type="button">Load Image</button>
        <img ng-src="{{image.path}}" preloadable />
    </div>

CSS:
    img[preloadable].empty{
        width:0; height:0;
    }

    img[preloadable]{
        width:auto; height:auto;
    }

JS:
    // Very "thin" controller:
    app.controller('MyCtrl', function($scope) {
       $scope.loadimage = function () {
            $scope.image.path = $scope.image.tmp_path;
       }
    });

    // View's logic placed in directive 
    app.directive('preloadable', function () {        
       return {
          link: function(scope, element) {
             element.addClass("empty");
             element.bind("load" , function(e){
                element.removeClass("empty");
             });
          }
       }
    });

Working Plunk: http://plnkr.co/edit/HX0bWz?p=preview

Community
  • 1
  • 1
Ivan Chernykh
  • 38,282
  • 12
  • 125
  • 141
0

This worked for me (using twitter bootstrap for the classes):

mainfile.js file (in products array):

{
  name: 'Custom Products',
  size: {width: 15, height: 15},      
  images:{thumbnail:"img/custom_products/full_custom_3.jpg"}
}

index.html file:

      <div class="gallery">
        <div class="img-wrap">
            <ul class="clearfix">
                <li class="small-image pull-left thumbnail">
                    <img ng-src="{{product.images.thumbnail}}" style="height:{{product.size.height}}em; width: {{product.size.width}}em" />
                </li>
          </ul>
        </div>
      </div>
Blairg23
  • 8,642
  • 5
  • 61
  • 61