11

I've been able to upgrade an angularjs element directive to be used in angular 4. Here's a sample code:

[myScores.js]

angular.module('app.components.directives.myScores', [])
.directive('myScores', function() {
  return {
    scope: {
      score: '=',
    },
    template: '<div>&gt;&gt;&gt; Your score is {{score}} &lt;&lt;&lt;',
    link: function(scope) {
      console.log("in myScores", scope)
    }
  };
});

[myScores.ts]

import { Directive, ElementRef, Injector, Input, Output, EventEmitter } from '@angular/core';
import { UpgradeComponent } from '@angular/upgrade/static';

@Directive({
  selector: 'my-scores'
})
export class MyScoresDirective extends UpgradeComponent {
  @Input() score: number;

  constructor(elementRef: ElementRef, injector: Injector) {
    super('myScores', elementRef, injector);
  }
}

Notice I'm using UpgradeComponent to upgrade the myScores element directive. I've tried the same on an attribute directive but got an error. Is there a way to upgrade an attribute directive?

Here's my attempt of upgrading an attribute directive:

[makeGreen.js]

angular.module('app.components.directives.makeGreen', [])
.directive('makeGreen', function() {
  return {
    restrict: 'A',
    link: function(scope, element) {
      console.log("in makeGreen", scope)
      console.log("element", element)
      element.css('color', 'green');
    }
  };
});

[makeGreen.ts]

import { Directive, ElementRef, Injector, Input, Output, EventEmitter } from '@angular/core';
import { UpgradeComponent } from '@angular/upgrade/static';

@Directive({
  selector: '[makeGreen]'
})
export class MakeGreenDirective extends UpgradeComponent {
  @Input() count: number;
  @Output() clicked: EventEmitter<number>;

  constructor(elementRef: ElementRef, injector: Injector) {
    console.log("elementRef", elementRef.nativeElement)
    super('makeGreen', elementRef, injector);
  }
}

I get an error when loading a page that has something like:

<div makeGreen>Text should be green</div>

I got this error:

Error: Directive 'makeGreen' is not a component, it is missing template.
FussinHussin
  • 1,718
  • 4
  • 19
  • 39
Will
  • 1,718
  • 3
  • 15
  • 23
  • 2
    Did you get this working? – jamiebarrow Apr 05 '18 at 06:45
  • 2
    @jamiebarrow I gave up on this a long time ago. – Will Apr 05 '18 at 23:40
  • 1
    Okay, that's a pity, I guess it's easy enough to re-write the attributes in Angular, but yeah... if I don't have to yet it would be nice :) Thanks anyway for getting back to me – jamiebarrow Apr 09 '18 at 13:04
  • 3
    @jamiebarrow I found a way to expose AngularJS directive in Angular 2 (now 5). Write an Angular JS component to consume Angular JS directive and upgrade that component in Angular 2. This means you must run AngularJS 1.5 or higher. – Will Apr 09 '18 at 16:06
  • @Will, please check my answer and let me know if it works by accepting it as answer. – nircraft Nov 06 '18 at 15:12
  • @Will have you an example of exposing AngularJS directive to Angular 5, I am currently dealing with a closed source third party AngularJS directive that needs to be utilized in Angular 5 component. UPDATE: I found your example but my ngJS directive is an Attribute directive :( – pateketu Nov 29 '18 at 15:00
  • 3
    @pateketu As of Aug. 2017, I didn't find a way to migrate attribute directives to Angular 4. It wasn't possible. Not sure if the Angular team has made this possible since. I wouldn't hold my breath though. – Will Nov 30 '18 at 23:58

1 Answers1

0

A Attribute directive can totally have the Input property which can be passed to it from the tag where it's used : For ex:

<p highlightThis [highlightColor]="'orange'" [count]="5">Highlighted in orange</p>

Also make sure your appModule/SharedModule imports it.

So the problem i see is with the way you are defining your structural directive. A structural directive doesn't have any template structure attached to it. It applies to any html tag where it's used.

For you case, i see you are extending the directive with Component class which is not acceptable to a Attribute directive :--

MakeGreenDirective extends UpgradeComponent {

You should keep the Attribute Directive separate from any Component. For Ex:

  import { Directive, ElementRef, Injector, Input, Output, EventEmitter } from 
  '@angular/core';

  @Directive({
    selector: '[highlightThis]'
   })

 export class HighLightThisDirective {
 @Input() count: number;
 @Input() highlightColor: string;
 @Output() clicked: EventEmitter<number>;

 constructor(private elementRef: ElementRef, injector: Injector) {  }

 ngOnInit(): void {
   this.decorateMyTag();
 }

 private decorateMyTag(): void {
   console.log("highlightColor", this.highlightColor);
   this.elementRef.nativeElement.style.backgroundColor = this.highlightColor;
  }
}
nircraft
  • 8,242
  • 5
  • 30
  • 46
  • 5
    This does not answer the question. You are providing an Angular solution, where the question asks how to upgrade (i.e., using `@angular/upgrade/static`) an AngularJS directive. – Huon Jun 12 '20 at 06:53
  • If you care to read through the question, it talks about upgrading to angular 4 and using it there. please check the comments too on question – nircraft Jun 12 '20 at 17:45