4

I am trying to implement a Crop Plugin Library in my angular demo project. I have injected the required modules to my main module and successfully cropped a pic. But I don't know how to pass the base64 string to the controller. What I have tried so far is:

var myApp = angular.module('myModule', ['ngRoute', 'angular-img-cropper', 'app']);

myApp.config(function($routeProvider) {
        $routeProvider
            .when('/multiple',{
                    templateUrl: 'templates/multi.html',
                    controller: 'multiController',
                    controllerAs: 'multiCtrl'           
            })
});

myApp.controller('multiController', function ($scope,$rootScope) {
        var vm = this;
        vm.clickButton = function () {
            console.log("photo: "+vm.member_photo);
        };
});

HTML - templates/multi.html:

<h1>Multi page which has another controller inside</h1>
<div ng-controller="multiController">
    <div ng-controller="ImageCropperCtrl as ctrl">
    <input type="file" img-cropper-fileread image="cropper.sourceImage"   />
    <div>
      <canvas width="500" height="300" id="canvas" image-cropper image="cropper.sourceImage" cropped-image="cropper.croppedImage" crop-width="500" crop-height="200" min-width="100" min-height="50" keep-aspect="true" crop-area-bounds="bounds"></canvas>
    </div>
    <div>Cropped Image (Left: {{bounds.left}} Right: {{bounds.right}} Top: {{bounds.top}} Bottom: {{bounds.bottom}})</div>
    <div ng-show="cropper.croppedImage!=null"><img ng-model="member_photo1" ng-src="{{cropper.croppedImage}}" /></div>
        <textarea name="member_photo" ng-model="multiCtrl.member_photo" id="member_photo" class="form-control valid">{{cropper.croppedImage}}</textarea>
    </div>
  <button ng-controller="insideController" ng-click="multiCtrl.clickButton()">Console.log</button>
</div>

If I inspect the textarea the value is there but it is not shown inside the textarea and also the value cannot be accessed inside my controller. What am I doing wrong?

1
  • You are using controller as syntax without specifying an alias for controller in the HTML. You need to use ng-model="vm.member_photo". same for your ng-click. Also you are both having ng-model and {{}} with is equivalent to ng-bind. You need to use one only Commented Oct 4, 2016 at 4:45

3 Answers 3

3
+50

As @Taylor Buchanan has already pointed out there are multiple issues with your code. And I too recommend that you review Angular documentation and examples.

Apart from the issues that @Taylor Buchanan has pointed out, I can see that you have used 3 different controllers in your template. multiController, ImageCropperCtrl & insideController. I don't understand why those many controllers are needed.

Also you don't need separate ng-model at textarea.

Looking at your requirement I think a single controller is sufficient. Here is sample code @ plunker that shows how the image cropper can be used and how you can get the cropped image data in controller.

script.js

angular.module('myApp', ['angular-img-cropper']);

angular.module('myApp').controller("multiController",[ '$scope', function($scope)
{
    $scope.cropper = {};
    $scope.cropper.sourceImage = null;
    $scope.cropper.croppedImage   = null;
    $scope.bounds = {};
    $scope.bounds.left = 0;
    $scope.bounds.right = 0;
    $scope.bounds.top = 0;
    $scope.bounds.bottom = 0;

    $scope.clickButton = function () {
        console.log("photo: "+ $scope.cropper.croppedImage);
    };
}]);

index.html

<!DOCTYPE html>
<html>

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

  <body ng-app="myApp" ng-controller="multiController">
    <h1>Image Cropper Demo</h1>
    <div>
      <input img-cropper-fileread="" image="cropper.sourceImage" type="file" />
      <div>
        <canvas width="500" height="300" id="canvas" image-cropper="" image="cropper.sourceImage" cropped-image="cropper.croppedImage" crop-width="400" crop-height="200" keep-aspect="true" touch-radius="30" crop-area-bounds="bounds"></canvas>
      </div>
      <div>Cropped Image (Left: {{bounds.left}} Right: {{bounds.right}} Top: {{bounds.top}} Bottom: {{bounds.bottom}})</div>
      <div ng-show="cropper.croppedImage!=null">
        <img ng-src="{{cropper.croppedImage}}" />
      </div>
      <textarea name="member_photo" id="member_photo" class="form-control valid">{{cropper.croppedImage}}</textarea>
      <button ng-click="clickButton()">Console.log</button>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
    <script src="angular-img-cropper.min.js"></script>
    <script src="script.js"></script>
  </body>

</html>

Note: As I have not used route provider, I had to explicitly specify ng-controller at body level. When you use route provider you don't need to specify ng-controller in your template. Check the example given at $route

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

5 Comments

Thanks for the help. I am newb to Angular. And that insideController was a mistake in the code. I actually used the multiController and ImageCropperCtrl. In that multiController was mine and ImageCropperCtrl was the cropper's. I thought ImageCropperCtrl was required for cropping. Still I don't get it. The cropper will be available just by injecting the module? And the cropper is accessible inside multiController?
We are defining cropper object inside our controller and using it in html. You can name it whatever you want but you will need to use that same variable in your html. And for the cropping functionality angular-img-cropper has defined multiple directives (like img-cropper-fileread, image-cropper, image, cropped-image, ......) that do the magic of cropping the image and storing it in your variable which you assign to cropped-image. HTH
The code is working without the cropper object declared in the controller.
Ref: docs.angularjs.org/api/ng/directive/ngModel Note: ngModel will try to bind to the property given by evaluating the expression on the current scope. If the property doesn't already exist on this scope, it will be created implicitly and added to the scope.
Ya :) , just said.
0

You have to specify the callback function in your template and implement the crop callback function in your controller. For example :

In template:

crop-callback="myCallbackFunction"

In controller:

vm.myCallbackFunction = function(base64) {
  vm.resultImage = base64;
  $scope.$apply(); // Apply the changes.
};

3 Comments

I'm kind of new to angular. Could you please tell me where to put the callback call?
Ok, then you need to mention which exact library are you using for the crop feature.. any link to that library doc ?
It is mentioned in the question. In the first sentence itself. Here is it: github.com/AllanBishop/angular-img-cropper
0

You have a variety of issues, mostly stemming from copying and pasting the library example. If you are new to Angular, I strongly suggest reviewing the Angular documentation and examples prior to implementing any additional libraries. That being said, here are some of the issues:

  1. You are referencing a controller in the template that is not defined. ImageCropperCtrl is a controller defined in the example, but not in the code you provided.

    <div ng-controller="ImageCropperCtrl as ctrl">
    

    This can probably just be removed since you've created your own controller.

  2. You are referencing an object called cropper throughout the template that is not defined in your controller. You can see in the example where they declare the object in the ImageCropperCtrl controller prior to using it:

    $scope.cropper = {};
    

    Once this variable is declared in your controller, you will be able to access the cropped image with $scope.cropper.croppedImage.

  3. You are attempting to reference your controller throughout the template as multiCtrl. This will only work if you use the controller as syntax (similar to what is shown in the library example: ImageCropperCtrl as ctrl).

    <div ng-controller="multiController">
    

    would become:

    <div ng-controller="multiController as multiCtrl">
    
  4. You are using both ng-model and interpolation ({{}}) for the textarea. You probably only want ng-model, but I'm not really sure what you're trying to do here.

1 Comment

All of the issues I've pointed out are valid. If you're going to downvote, leave an actual reason.

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.