8

I have a simple AngularJS / FabricJs application, the intent is to allow an image to be moved /re-sized prior to upload. Essentially four steps:

1) I present a form with a canvas, and a rectangle inside of form to represent a clip area 
2) browse for a local file 
3) add it to the canvas 
4) and have a button to capture the clip area inside of the canvas

The problem occurs when I move the code from a directly embedded form to sitting behind an angular directive. Once I moved the form into the directive an issue popped up, the image is loaded and added to the canvas without (any obvious) issues. However once you click anywhere on the canvas (for instance, in an attempt to move the image) the image you added no longer appears on the canvas (although inspection of the fabricJs Canvas object still shows it as inside of its object array).

The JS App and helper:

var myApp = angular.module('myApp', [])

// helper function to bind tot he on change of a input/file object (angularJs workaround)
var invokeImageChange = function(that) {
    angular.element(that).scope().imageChange(that)
    angular.element(that).scope().$digest();
}

Controller:

var ImageCtrl = function($scope) {

    var desiredHeight = 300
    var desiredWidth = 770

    // I understand this docucment.gelElementById is not the angular way - and needs to be changed
    var myImageData = document.getElementById('fileData')
    var myImage = document.getElementById('myImage')
    var canvas = new fabric.Canvas('myCanvas')

    var rect = new fabric.Rect({
        fill: 'lightgray',
        left: canvas.width / 2,
        top: canvas.height / 2,
        width: desiredWidth,
        height: desiredHeight,
        stroke: 'darkgray',
        strokeDashArray: [5, 5],
        selectable: false
    });
    canvas.add(rect)
    var clipZone = {
        y: rect.top - (.5 * rect.height),
        x: rect.left - (.5 * rect.width),
        width: desiredWidth,
        height: desiredHeight,
        quality: 1
    }

    $scope.caption = "" ;
    $scope.fileUrl = "" ;

    $scope.imageChange = function(inp)  {
        console.log('imageChange')
        file = inp.files[0];
        fr = new FileReader();
        fr.onload = createImage;
        fr.readAsDataURL(file);

        var img = null

        function createImage() {
            console.log('createImage')
            img = new Image();
            img.onload = imageLoaded;
            img.src = fr.result;
        }

        function imageLoaded() {
            console.log('imageLoaded')
            var fabImg = new fabric.Image(img)

            fabImg.scale(1.0).set({
                left: canvas.width / 2,
                top: canvas.height / 2
            });

            canvas.add(fabImg)
            canvas.setActiveObject(fabImg)
        }
    }

    $scope.submit = function(event) {

    }

    $scope.capture = function() {
        console.log('capture')

    }
}

The Directive code:

myApp.directive('ngImageEditor', function() {
  return {
    restrict: 'E',
    transclude: true,
    replace: true,
    controller: 'ImageCtrl',
    templateUrl: '\blah\pathToForm'
  };
});

where the TemplateUrl refers to this form

<form name="uploadForm" ng-controller="ImageCtrl" method="post" enctype="multipart/form-data"
      action="/main/update" ng-submit="submit()">
    <div class="control-group">
        <label class="control-label" for="file">Image File</label>
        <div class="controls">
            <input type="file" name="file" ng-model="file" onchange="invokeImageChange(this)"/>
            <input type="text" id="fileData" name="fileData" ng-model="fileUrl"/>
        </div>
    </div>
    <div class="control-group">
        <div class="controls">
            <input type="button" value="Upload"  ng-click="capture()"/>
        </div>
    </div>
    <div>
        <canvas id="myCanvas" width="800" height="400" style="border:1px solid #000000;"></canvas>
    </div>
    <img id="myImage" style="border: 1px solid burlywood">
</form>

Hopefully the JsFiddle below helps folks understand what I am talking about. Thanks in advance!

To reproduce

1) browse to an image
2) move the image (notice the image disappears in the second link)

Working (image can be moved) (without directive):

http://jsfiddle.net/PNwbp/1/

Broken / Issues (image disappears when moved) (with directive):

http://jsfiddle.net/faFVW/23/

1 Answer 1

6

Remove the ng-controller="ImageCtrl" from your template, in is creating another $scope and instance of the Controller, and that breaks it.

<form name="uploadForm" /*ng-controller="ImageCtrl"*/ method="post" enctype="multipart/form-data"
      action="/main/update" ng-submit="submit()">
Sign up to request clarification or add additional context in comments.

3 Comments

My man! Thank you that was driving me batty - moving to the directive was more of Proof of Concept - so perhaps I moved too quickly through the code required for them to work (first time porting to / coding a directive). Alternatively I can remove the controller from the directive code and that works as well.
Brian, can you please help down the knowledge curve by letting me know how you diagnosed the problem? Is this a common angular error, at least common enough it is something to be cognizant of? Or did you employ another technique?
I have been working with angular for a while i just noticed that and removed it from you jsfiddle to see if it worked and it did. check out the angular-ui.github.io/bootstrap project. The implement directive really well, its a good resource.

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.