Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declare a component with generic type

Is it possible to declare a component with a generic type in Angular 4?

The following code causes build errors:

export class MyGenericComponent<T> implements OnInit {     @Input()  data: BehaviorSubject<T[]>;      //... } 

The error when executing ng serve is:

ERROR in C:/.../my-generic.module.ts (5,10): Module '"C:/.../my-generic.component"' has no exported member 'MyGenericComponent'. 

Example:

The following example is an attempt to implement a generic data table where @Input() data changes from one component 'calling this component' to another. The question is could BehaviorSubject<any[]> be changed to BehaviorSubject<T[]> where T would be the generic type passed to the component?

@Component({   selector: 'my-data-list',   templateUrl: './data-list.component.html',   styleUrls: ['./data-list.component.css'] }) export class DataListComponent implements OnInit {   @Input()  data: BehaviorSubject<any[]>;   @Output() onLoaded = new EventEmitter<boolean>();    private tableDataBase : TableDataBase = new TableDataBase();   private dataSource : TableDataSource | null;    constructor() { }    ngOnInit() {     this.tableDataBase.dataChange = this.data;     this.dataSource = new TableDataSource(this.tableDataBase);     this.onLoaded.emit(true);   } }  class TableDataBase {   dataChange: BehaviorSubject<any[]> = new BehaviorSubject<any[]>([]);    get data(): any[] {     return this.dataChange.value;   } }  class TableDataSource extends DataSource<any> {    constructor(private tableDataBase: TableDataBase) {     super();   }    connect(): Observable<any[]> {     return Observable.of(this.tableDataBase.data);   }    disconnect() {} } 
like image 856
Strider Avatar asked Oct 23 '17 16:10

Strider


People also ask

How do you create a generic component?

Generic Component To use a generic, we simply add the generic parameter between the symbols < and > right after the item and component's props definition, let's call it T, like below. Notice that as long as we apply a generic parameter to our types we need to declare it after all the types usages.

What is generic component?

Generic Components means any code, algorithm, materials, process or other items of Deliverables that have been developed or created by Thinktiv that are owned by Client and do not include or disclose any Client Confidential Information.

What is generic component in angular?

In TypeScript, generics can be used to better describe the types in classes that are reusable with multiple derived types. Angular does not support instantiation of generic components, but this limitation can be worked around by creating a derived component for each derived type we want to use it with.


2 Answers

You can also access the Type parameter through the ViewChild like this:

export class Bazz {   name: string;    constructor(name: string) {     this.name = name;      } }  @Component({   selector: 'app-foo',   template: `<div>{{bazz?.name}}</div>`,   exportAs: 'appFoo' }) export class FooComponent<T> {   constructor() {}   private _bazz: T;    set bazz(b: T) {     this._bazz = b;   }    get bazz(): T {    return this._bazz;   } }  @Component({   selector: 'app-bar',   template: `<app-foo #appFoo></app-foo>`,   styleUrls: ['./foo.component.scss'], }) export class BarComponent<T> implements OnInit {   @ViewChild('appFoo') appFoo: FooComponent<Bazz>;    constructor() {}    ngOnInit() {     this.appFoo.bazz = new Bazz('bizzle');     console.log(this.appFoo.bazz);   } } 
like image 181
Matt Ringer Avatar answered Nov 05 '22 11:11

Matt Ringer


You can declare it, but cannot use it directly. You can do something like this:

export abstract class Form<T> implements OnInit, OnChanges {   someMethod() { throw 'Dont use directly' }   otherMethod() { return 'Works!'; }   // Note that below will cause compilation error   //   TypeError: Object prototype may only be an Object or null: undefined   // You cannot use protected in this usecase   protected anotherMethod() { } }  @Component({}) export class ModelOneForm extends Form<ModelOne> {   someMethod() { return this.otherMethod(); } } 
like image 25
Sasxa Avatar answered Nov 05 '22 12:11

Sasxa