I\'m doing a small project to play around the goody bag the ES6 is bringing, I\'m trying to set register a class as an angular directive, but I\'m running into this error \"
@Michael is right on the money:
the module.directive() method expects a factory function
However I solved it using another technique, a little cleaner I suppose, It works fine for me, it's not perfect though... I defined a static method that returns a the factory expected by module()
class VineDirective {
constructor($q) {
this.restrict = 'AE';
this.$q = $q;
}
link(scope, element, attributes) {
console.log("directive link");
}
static directiveFactory($q){
VineDirective.instance = new VineDirective($q);
return VineDirective.instance;
}
}
VineDirective.directiveFactory.$inject = ['$q'];
export { VineDirective }
And in my app I do:
angular.module('vineyard',[]).directive('vineScroller', VineDirective.directiveFactory)
I believe there's no other way to use classes + directives that going through hacks like this at this point, just pick the easy one ;-)
My solution:
class myDirective {
constructor( $timeout, $http ) {
this.restrict = 'E';
this.scope = {};
this.$timeout = $timeout;
this.$http = $http;
}
link() {
console.log('link myDirective');
}
static create() {
return new myDirective(...arguments);
}
}
myDirective.create.$inject = ['$timeout', '$http'];
export { myDirective }
and in the main app file
app.directive('myDirective', myDirective.create)
I had a similar problem. But in my case it worked and failed when I deployed to production. And it failed because production has the latest version of 6to5.
This could be prevented by using npm shrinkwrap
.
According to the latest ES6 spec you can't use a class like this. https://github.com/babel/babel/issues/700
As mentioned in a comment, the module.directive()
method expects a factory function rather than a constructor.
The most simple way would be to wrap your class in a function that returns an instance:
angular.module('app')
.directive('dateBlock', () => new DateBlock());
However, this will only work in the most limited sense - it does not allow for dependency injection and the compile
and link
functions of your directive (if defined) will not work as expected.
In fact, this is a problem I have looked into quite extensively and it turned out to be fairly tricky to solve (for me at least).
I wrote an extensive article covering my solution, but as far as you are concerned I can point you to the discussion of the two main issues that need to be resolved:
Dynamically converting a class definition into an angular-compatible factory function
Allowing a directive's link and compile functions to be defined as class methods
The full solution involves too much code to paste here, I think, but I have put together a working demo project which allows you to define a directive as an ES6 class like this:
class MyDirective {
/*@ngInject*/
constructor($interval) {
this.template = '<div>I\'m a directive!</div>';
this.restrict = 'E';
this.scope = {}
// etc. for the usual config options
// allows us to use the injected dependencies
// elsewhere in the directive (e.g. compile or link function)
this.$interval = $interval;
}
// optional compile function
compile(tElement) {
tElement.css('position', 'absolute');
}
// optional link function
link(scope, element) {
this.$interval(() => this.move(element), 1000);
}
move(element) {
element.css('left', (Math.random() * 500) + 'px');
element.css('top', (Math.random() * 500) + 'px');
}
}
// `register` is a helper method that hides all the complex magic that is needed to make this work.
register('app').directive('myDirective', MyDirective);
Check out the demo repo here and here is the code behind register.directive()