来自公共源的角度条件组件



首先,我想说的是,我不是一个棱角分明的开发人员,我几乎所有的技能都属于后端工作,但我正在努力实现这个概念,我甚至不知道这是否可能。谷歌搜索并没有多大帮助,因为我甚至不知道如何正确地表达这个问题,所以我希望描述一下情况,我想做什么,我希望它如何工作,并希望得到一些建议,告诉我我试图做的事情在Angular世界中实际上被称为什么,它是否可能,假设它可能,它会是什么样子的一个例子。

我们有一个SPA,它有一个.NET核心Web API后端。有一个API端点/api/feedItems,它返回一个"提要项"列表,大致相当于事件日志。

馈送项目的基本形状类似于:

export enum FeedItemType {
undefined = "undefined",
foo = "foo",
bar = "bar"
}
export class FeedItemModel {
id: number;
createdUtcTimestamp: Date;
feedType: FeedItemType;
feedData: {} // object? any?
}

这里的想法是,所有提要项都将具有特定的元数据,包括id、时间戳、提要类型标识符和有效负载。实际有效载荷内容将基于CCD_ 2而不同。

从API调用返回的示例提要项列表可能类似于以下内容:

[  
{  
"id":12345,
"createdUtcTimestamp":"2018-12-05T13:30:00Z",
"feedType":"foo",
"feedData":{  
"name":"this is a foo type feed",
"description":"This foo feed is describing an event of type 'foo'"
}
},
{  
"id":67890,
"createdUtcTimestamp":"2018-12-06T15:45:00Z",
"feedType":"bar",
"feedData":{  
"value1":11111,
"value2":22222,
"value3":33333
}
}
]

实际上,我们有很多不同的提要项类型,每种类型都应该有自己的自定义呈现,以最有用的方式可视化数据。

我想做的是有一个angular组件,负责从API获取提要项列表并循环遍历提要项。对于每个提要项(可能在*ngFor指令中(,它应该呈现公共属性,然后基于feedType呈现不同的"子"组件。

在这种情况下,假设我的容器组件如下所示:

<div class="feed-item-container" *ngFor="let feedItem of feedItemList; let i = index;">
<div class="feed-item">
<div class="timestamp-display">{{feedItem.createdUtcTimestamp}}</div>
<!-- equivalent of "if feedItem.feedType == 'foo'", 
possibly ngIf or ngSwitch, but I'd prefer to not 
have to explicitly check for each type -->
<feed-item-foo (I have no idea how to pass the feedData to this component) />
<!-- equivalent of "if feedItem.feedType == 'bar'" -->
<feed-item-bar (again, this is a mystery what should go here) />
<!-- equivalent of "if can't match on feedType" -->
<feed-item-generic (something) />
</div>
</div>

这里的想法是,我可以根据需要在该文件之外创建组件,而无需对容器模板进行许多更改(最好是不进行任何更改(。如果我能以编程方式识别feedType,为它寻找一个注册的组件选择器,并自动将feedData传递给它,那将是理想的选择,但如果我必须手动引用这个容器中的每个组件,那也没关系。我只是不想把所有的渲染逻辑都放在这个容器中,因为这很快就会变得笨拙和难以管理。

提要项组件将根据提要类型有自己的格式,也有不同的样式,也许还有不同的逻辑操作。我不想要一个巨大的feedItem容器组件。

那么,这可能吗?如果是的话,我该怎么办?

如果我能正确理解,也许下面的想法可以帮助你。。我以你为例,稍作修改。

<div class="feed-item-container" *ngFor="let feedItem of feedItemList; let i = index;">
<div class="feed-item">
<div class="timestamp-display">{{feedItem.createdUtcTimestamp}}</div>
<!-- equivalent of "if feedItem.feedType == 'foo'", 
possibly ngIf or ngSwitch, but I'd prefer to not 
have to explicitly check for each type -->
<!-- i do not know of any alternative, but to make it a bit more readable
you can use <ng-container>
<ng-container *ngIf="feedItem.feedType === 'foo'">
<!-- you can create your own component and add an @Input() data, so your component will know what it is dealing with (see example below)
<feed-item-foo [data]="feedItem"/>
</ng-container>
<!-- equivalent of "if feedItem.feedType == 'bar'" -->
<ng-container *ngIf="feedItem.feedType === 'bar'">
<!-- you can create your own component and add an @Input() data, so 
your component will know what it is dealing with (see example below)
<feed-item-bar [data]="feedItem"/>
</ng-container>
<!-- equivalent of "if can't match on feedType" -->
<!-- that is a bit of a pain in the ... --> 
<ng-container *ngIf='!foo && !bar && !xyz'>
<feed-item-generic (something) />
</ng-container>
</div>

您的组件可以而且应该都包括类似于"基本"类的东西

export class FeedItemBase implements OnInit {
@Input() data = <YourType>null; // that is a little hack to get the type 
// correct (was some bug in a angular 4 version as far as i remember)
constructor() {
}
ngOnInit() {
// if needed .. if not, delete it :)
}
}

那么所有其他类都可以扩展基类(因为数据总是一样的…

export class FeedItemFoo extends FeedItemBase implements OnInit {
constructor() {
}
ngOnInit() {
// here you can access data already 
}
}

如果你只有两种类型(我怀疑(,你也可以这样做:

<div class="feed-item-container" *ngFor="let feedItem of feedItemList; let i = index;">
<div class="feed-item">
<div class="timestamp-display">{{feedItem.createdUtcTimestamp}}</div>
<!-- equivalent of "if feedItem.feedType == 'foo'", 
possibly ngIf or ngSwitch, but I'd prefer to not 
have to explicitly check for each type -->
<!-- i do not know of any alternative, but to make it a bit more readable
you can use <ng-template>
<ng-container *ngIf="feedItem.feedType === 'foo'; then fooId;else barId"> 
</ng-container>
<ng-template #fooId>
<!-- you can create your own component and add an @Input() data, so your component will know what it is dealing with (see example below)
<feed-item-bar [data]="feedItem"/>
</ng-template>
<!-- equivalent of "if feedItem.feedType == 'bar'" -->
<ng-template #barId>
<!-- you can create your own component and add an @Input() data, so 
your component will know what it is dealing with (see example below)
<feed-item-foo [data]="feedItem"/>
</ng-container>
<!-- equivalent of "if can't match on feedType" -->
<!-- that is a bit of a pain in the ... --> 
<ng-container *ngIf='!foo && !bar && !xyz'>
<feed-item-generic (something) />
</ng-container>
</div>

希望有帮助:(

最新更新