0

I need the dimensions of an image loaded from the web (dynamically) to adapt my display. So I need to use an onload event in the controller (the view is not rendered yet), like so :

.controller("MyCtrl", function($scope){
    img.onload = function () {
        // $scope changes not effective
}

I know I could use $apply, but I'm not a huge fan of it since it hurts performances. Do you have any other solution I could use, whether for Angular to be aware of what I'm doing (which is not the case with img.onload) or for the scope to take my changes into account?

Thanks!

2
  • 1
    Controllers should never be aware of the DOM attached to them. I'm not sure I understand exactly what you're trying to do? You want to tell the image what size to be based on some server response, or are you trying to get the dimensions of the image and use them in your controller? Commented Oct 14, 2015 at 9:02
  • I'm not trying to get anything from the DOM, just, as you said in second, get the dimension of the image and use them in my controller. Which is not possible until the image have loaded, if I'm not wrong - that's why I used img.onload Commented Oct 14, 2015 at 9:04

3 Answers 3

1

You need to use a directive to fetch the image properties, and assign them to your scope in the controller. Here is some pseudo-code, can't guarantee it'll 100% work out of the box, but it should give you an idea on what needs to happen.

Template

<div ng-controller="MyCtrl">
    <img img-size src="..." />
</div>

Directive

.directive('imgSize', function() {
    return {
        link: function (scope, elem, attrs) {
            elem.on('load', function(e) {
                var width = $(this).width();
                var height: $(this).height();

                scope.$evalAsync(function() {
                    scope.imageWidth = width;
                    scope.imageHeight = height;
                });
            });
        }
    }
});
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks, that's a solution I thought about a lot, but as I said the view is not rendered yet - and I don't want to display the image yet, since its container styling depends a lot on its dimensions. A loader is displayed until the img.onload finishes. I guess I will have to use $apply, in the end...
Don't use $apply, you'll just run into conflicts with Angular's own digest cycle. This is what $evalAsync is for - it will run during the current digest if possible, or in the next one, like $timeout would.
So you say I should take a look into $evalAsync and that's my best bet ?
Any changes to the scope you do outside of Angular's digest cycle will not update the DOM. For instance, the load event. When you use ng-click or any other directive, angular handles $apply for you. In order for your DOM to update when you change the scope outside of Angular, you need to call $evalAsync on your scope, or $timeout.
Thank you very much. I will wait for a little bit and mark your answer as accepted, since you provided me the most help here. You're great.
0

Use a directive that will inject the height/width in the the controller $scope.

<img height-width />

1 Comment

Hey, thanks for answering. The image is not in the view (yet), I want to get the dimension of the image and use them in my controller before the view renders. That's why I used img.onload
0

I assume you have your image in the current View. You could access it with something like:

var elImage = document.getElementById("[your_imageId]")

After that

elImage .addEventListener('load', function() { /* ... */ }, false);

should get you further.

2 Comments

While this will technically work, this is not the correct solution. Controllers should never have DOM element queries inside of them.
Hey, thanks for answering. The image is not in the view (yet), I want to get the dimension of the image and use them in my controller before the view renders. That's why I used img.onload

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.