问题
I try to build a reusable list which displays elements of type T. The view of these elements depends on T. To break this dependency I decided to also pass the view component.
E.g. The list contains elements of type "Car". The view passing to this list is used to display the attributes ".ps" and ".color" of each element.
Sadly, I am a Newbie in Angular and I can't figure how to do this right. I would like to do something like this:
generic-list.ts
export class GenericListComponent<T> {
@Input() readonly elements: T[]; // Array of objects to be listed;
@Input() embeddedComponentAsViewForEachGivenElementOfTypeT: any;
...
}
generic-list.html
<mat-list>
<mat-list-item *ngFor="let el of elements">
<embeddedComponentAsViewForEachGivenElementOfTypeT [element]=el </embeddedComponentAsViewForEachGivenElementOfTypeT>
</mat-list-item>
</mat-list>
Using the list could look like this :
<app-generic-list [elements]="ArrayOfComplexObjects"
[embeddedComponentAsViewForEachGivenElementOfTypeT]="ViewComponentToDisplayComplexObject"> </app-generic-list>
Any ideas ? Thanks :)
---- Update:
I take Brandons answer but changed the implementation a little bit by using *ngSwitchCase and adding a factory component. The bad thing about this approach is that everytime a new ListElement comes in, the factory component has to be modfied (violation of "Open-Close-Principle". On the other hand is this dependency kept in one factory.
Here is the Code:
generic-list-html
<mat-list>
<mat-list-item *ngFor="let el of elements">
<app-factory-listelement elementToDisplay="el" typeOfListElement="carListElement"> </app-factory-listelement>
</mat-list-item>
</mat-list>
factory-listelement.ts
export class FactoryListelementComponent implements OnInit {
@Input() typeOfListElement: string;
@Input() elementToDisplay: any;
carType = 'carListElement';
bikeType = 'bikeListElement';
...
factory-listelement.html
<div [ngSwitch]="typeOfListElement">
<app-car-info-list-element TheCarElement="elementToDisplay" *ngSwitchCase="carType" >...</app-car-info-list-element>
<app-bike-info-list-element TheBikeElement="elementToDisplay" *ngSwitchCase="bikeType" >...</app-bike-info-list-element>
<!--default case when there are no matches -->
<div *ngSwitchDefault> ERROR ! Make some error.log or so</div
</div>
回答1:
I don't believe that's possible. The HTML element used to reference the "embeddedComponent..." is not data binded like element attributes can be. What you could do is have a restricted number of child components within the list and pass a parameter like type
in, which would instruct the component to use one of the available child components.
So then in generic-list.html you'd have something like:
<mat-list>
<mat-list-item *ngFor="let el of elements">
<component-option-one
*ngIf="type === 'componentOptionOne'"
></component-option-one>
<component-option-two
*ngIf="type === 'componentOptionTwo'"
></component-option-two>
<component-option-three
*ngIf="type === 'componentOptionThree'"
></component-option-three>
</mat-list-item>
</mat-list>
And you'd create it with:
<app-generic-list
[elements]="arrayOfElements"
[type]="'componentOptionOne'"
></app-generic-list>
来源:https://stackoverflow.com/questions/54189164/angular-pass-component-to-component-as-parameter