Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 AOT compiler does not support mixins

Sometimes I use Mixins to inject repeated functions like slugUrl().

But it doesn't work with angular 4 compiler.

export function Mixin(decorators: Function[]) {
  return function (classFn: Function) {
    decorators.forEach(decorator => {
      Object.getOwnPropertyNames(decorator.prototype).forEach(name => {
        classFn.prototype[name] = decorator.prototype[name];
      });
    });
  };
}


@Mixin([BehaviorInjected])
export class FooComponent {

}

If I compile this code, compiler throws:

Property 'ngClassControl' does not exist on type 'FooComponent'.

Any ideas?

Edit: Since there was someone who asked, here's another example using TS mixins that reproduces the issue, this time at template level.

Components:

@Component({
    selector: 'home-page',
    template: '<test [tag]="tag"></test>'
})
export class HomePageComponent extends TaggedComponent(MyComponent) {
    public tag = 'hi there';
}

@Component({
    selector: 'test',
    template: '<div></div>'
})
export class TestComponent extends TaggedComponent(MyComponent) {}

Mixins:

type Constructor<T> = new(...args: any[]) => T;

export function TaggedComponent<T extends Constructor<{}>>(Base: T) {
     class TaggedBase extends Base {
        @Input() tag: string;
     };

     return TaggedBase;
}

export class MyComponent {
    protected subscriptions: Subscription = new Subscription();
  // ...
}

Error:

ERROR in Error: Template parse errors: Can't bind to 'tag' since it isn't a known property of 'test'. ("][tag]="tag">")

like image 774
Serginho Avatar asked Apr 28 '17 11:04

Serginho


People also ask

What is AOT compiler how do you enable it?

The Angular ahead-of-time (AOT) compiler converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase before the browser downloads and runs that code. Compiling your application during the build process provides a faster rendering in the browser.

What are the ways to control AOT compilation?

When you use the Angular AOT compiler, you can control your app compilation in two ways: By providing template compiler options in the tsconfig. json file. By specifying Angular metadata.

Which of the following advantage does AOT give to an application WRT compilation?

Advantages of AOT compilationFaster rendering of your Angular application — With AOT, the code is compiled during the build process. Therefore, the browser loads executable code that is ready to be rendered immediately. Very fast!


2 Answers

The main problem here is that angular compiler has limited functionality.(read more in the docs)

AOT compiler uses metadata that is generated by MetadataCollector. It uses typescript object model(tree of Node)(that's why AOT can be used only with typescript) to gather all information that is necessary to produce ngfactory (in some cases also ngsummary) files.

The examples you provided are completely different for AOT compiler:

1) Custom decorator

@Mixin([BehaviorInjected])
export class FooComponent {}

Angular MetadataCollector will include @Mixin decorator in metadata of FooComponent symbol(item in decorators array) but it will be skipped when aot StaticReflector will call simplify since Mixin decorator is not registered in special map that includes only strictly defined decorators (source code)

Moreover if we even include it in that map it still won't be executed during aot compilation because it is only available for supported decorators.

2) Call custom function

export class HomePageComponent extends TaggedComponent(MyComponent) {

MetadataCollector will add TaggedComponent to metadata collection as symbol like {__symbolic: 'error', message: 'Symbol reference expected'}; but it also will be skipped inside StaticReflector.

And as far as i know there is currently no solution to support it.

like image 87
yurzui Avatar answered Oct 02 '22 14:10

yurzui


See https://github.com/angular/angular/issues/19145

I believe it is the same problem. Decorator inheritance is broken for mixins, so currently you will have to duplicate decorated properties.

like image 26
kemsky Avatar answered Oct 02 '22 14:10

kemsky