Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I want to use this pretty image cropper in my AngularJS project. When I use it the "normal" way, that is on a plain page, everything works fine. The problem is that I want to put it on to the Bootstrap modal dialog.

In order to initialize the cropper, I am supposed to execute this snippet:

$(".cropper").cropper({
    aspectRatio : 1.618,
    done : function(data) {
        console.log(data);
    }
});

But it has to be executed after the DOM of the modal is loaded. So I have tried to run it like this:

$scope.onCropOpen = function() {
    var modalInstance = $modal.open({
        templateUrl : 'cropModal.html',
        controller : CropModalInstanceCtrl
    });

    modalInstance.opened.then(function() {
        $(".cropper").cropper({
            aspectRatio : 1.618,
            done : function(data) {
                console.log(data);
            }
        });
    });
};

Unfortunately, the cropper still is not being initialized. I know that it should work after calling it when the modal is loaded, because I ran it manually from the browser console (with the modal dialog open) and then the cropper "magically" initialized.

share|improve this question
    
resolve your cropper object in $modal.open, but it's not best solution, you should have some factory which will return cropper constructor, and inside CropModalInstanceCtrl you will initialize it. –  evc Aug 12 '14 at 12:03

3 Answers 3

up vote 1 down vote accepted

Here is a very simple directive that can show you the direction. Instead of defining element with class ".cropper", create element "image-cropper" (since directive name is "imageCropper"):

<image-cropper></image-cropper>

This is a pretty general snippet that should work in similar way for any jquery plugin.

*Don't forget to change module name from "myApp", to the name of your application module...

angular.module("myApp").directive('imageCropper', function ($parse) {
            return {
                restrict: "E",
                replace: true,

                compile: function (element, attrs) {
                    var modelAccessor = $parse(attrs.ngModel);

                    var html = "<img></img>"; 
                    var newElem = $(html); 
                    newElem.attr("src", attrs.src);
                    element.replaceWith(newElem);

                    return function (scope, element, attrs, controller) {

                        element.cropper({
                            aspectRatio : 1.618,
                            done : function(data) {
                                console.log(data);
                            }
                        });

                    };

                }
            };
        });
share|improve this answer
    
Wow! Many thanks, works like a charm! I have modified it a little: var html = "<img></img>"; var newElem = $(html); newElem.attr("src", attrs.src); –  itachi Aug 12 '14 at 12:56

Try to put the jquery code inside CropModalInstanceCtrl function:

var CropModalInstanceCtrl = function ($scope, $modalInstance) {

   $(".cropper").cropper({
      aspectRatio : 1.618,
      done : function(data) {
         console.log(data);
      }
   });

}
share|improve this answer
    
Still doesn't work. This code executes before even the modal is shown, so it has no effect on the DOM. –  itachi Aug 12 '14 at 11:16
    
I have in mind some "dirty" solution. But better is to create a directive (thats the best practice for DOM manipulation). What do you prefer? –  Vitali Kaspler Aug 12 '14 at 11:48
    
Directives are elegant. So if you could show me how to do it, I would be grateful. –  itachi Aug 12 '14 at 12:22

Vitali's solution is done the proper way and definitely should be used. But if someone still needs a brute method, this worked for me as well:

modalInstance.opened.then(function() {
    $timeout(function() {
        $(".cropper").cropper({
            aspectRatio : 1.0,
            done : function(data) {
                console.log(data);
            }
        });
    });
});

Generally, this type of solutions should be avoided because timeouts might be treacherous.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.