7

I'm trying to build an app which edits simple graphics on screen, fabricjs is the canvas library I use, and angularjs is the MVW framework I use.

Now, the bindings from DOM to fabric work just fine (I click a div, and corresponding object on canvas gets selected), but not the other way around. When I click an object on canvas, and it gets selected the corresponding DOM isn't updated. I've read here that I should be using $scope.$apply();, but I'm not sure where to put that.

How do I make fabric update $scope state?

You can see the code here, click the Add Rect button to add elements to the canvas, and notice that when you click the element's name on the right it get's selected on the canvas, but if you select it directly on the canvas it's button isn't high-lit.

code: http://plnkr.co/edit/lMogPGjJOXx9HLAdiYqB

MeLight
  • 5,454
  • 4
  • 43
  • 67
  • Can you post a fiddle or something to show us the code. Typically you would use $scope.apply whenever you are in a code outside of the context of angularjs and $scope.$apply is the way to inform AngularJS to run the bindings and watchers. – rajasaur Aug 17 '13 at 20:00
  • @rajasaur thanks for the reply. I edited the question and added an example on Plunkr. – MeLight Aug 17 '13 at 20:40

2 Answers2

6

FabricJS implements events on its classes, so one could bind arbitrary listeners to them. In your case, you could bind a listener to the "object:selected" event, which would call $scope.$apply() and would be fired whenever a object is selected on canvas.

See the Event Inspector Demo and the Observable Class Documentation. The Canvas class inherits all these methods, so you could bind listeners to it. You can even retrieve the selected object, as in the example:

var canvas = new Fabric.Canvas('canvas_container');
canvas.on("object:selected", function (options, event) {
   var object = options.target; //This is the object selected
   // You can do anything you want and then call...
   $scope.$apply()
});
  • 1
    Bernardo that's exactly what I did :) Thanks for the reply though. The only thing is that if you do it from outside the scope, you should reference the scope like this: `var scope = angular.element(document.getElementById('canvas')).scope();` – MeLight Aug 24 '13 at 12:46
3

Based on the answer from Bernardo Domingues and MeLight's comment, it took me still some time to figure out.

The final solution for above is:

var canvas;

window.onload = function() {
    canvas = new fabric.Canvas('canvas');
    canvas.on("object:selected", function (options, event) {
        //var object = options.target; //This is the object selected 
        var scope = angular.element(document.getElementById('canvas')).scope();
        // You can do anything you want and then call...
        scope.$apply();
    });
};

The answer on AngularJS access scope from outside js function was very helpfull, together with http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

If you also want to see the position-information change when moving, add:

canvas.on("object:moving", function (options, event) {
    var scope = angular.element(document.getElementById('canvas')).scope();
    scope.$apply();
});
Community
  • 1
  • 1
Lambert
  • 310
  • 3
  • 8