Arthur  Kishinets Arthur Kishinets - 2 months ago 14
AngularJS Question

Angular controller is not defined

I want to create some event handler in my directive`s controller. Here is directive code:

module.exports = function() {
return {
restrict: 'EA',
bindToController: true,
scope: {
myarticle: '=article'
},
controllerAs: 'ctrl',
templateUrl: '../../views/draggableArticle.html',
link: function(scope, element, attr) {
},
controller: function() {
this.clicked = function() {
alert('clicked');
};
this.dragstartHandler = function() {
alert('draged');
};
}
};
};


And my view:

<div draggable="true" ondragstart="ctrl.dragstartHandler($event);" ng-click="ctrl.clicked()">
<h2>{{ctrl.myarticle.webTitle | limitTo: 40}}</h2>
<p>{{ctrl.myarticle.blocks.body[0].bodyTextSummary | limitTo: 200}}</p>
</div>


When I click on the block it works and alert "clicked", but when i drag a block it gives me an error


Uncaught ReferenceError: ctrl is not defined

Answer

ondragstart is native JS event fired from within global window scope, which is not aware of needed controller, while ng-click is fired from within controller's scope. We can load needed scope using angular.element(this).scope() function:

<div draggable="true" 
     ondragstart="angular.element(this).scope().ctrl.dragstartHandler();" 
     ng-click="ctrl.clicked()">
  <h2>{{ctrl.myarticle.webTitle | limitTo: 40}}</h2>
  <p>{{ctrl.myarticle.blocks.body[0].bodyTextSummary | limitTo: 200}}</p>
</div>

for the same reason angular $event is also unavailable, but you can still use all arguments passed to native function.

There is also angular module ngDraggable https://github.com/fatlinesofcode/ngDraggable, but it has an issue with firing drag start event - https://github.com/fatlinesofcode/ngDraggable/issues/89