Angular2:*ngFor、AsyncPipe 和索引
Angular2: *ngFor, AsyncPipe, and index
在上一个问题 中,我试图仅在 2 条消息之间发生变化时才显示日期。
区别在于我现在连接到一个实时数据库 (Firebase),所以我订阅了数据源并在通过索引和 *ngIf:
之前通过异步管道传递它
<div *ngFor='let message of (chat | async) ; let i = index'>
<button *ngIf="i == 0 || (message.timestamp | date: 'ddMMMMyyyy') != ((chat | async)[i-1].timestamp | date: 'ddMMMMyyyy')">
{{ message.timestamp | date:'ddMMM' }}
</button>
...
<!--More html elements below (omitted)-->
...
</div>
这在我第一次加载视图时效果很好,但是,如果我将新条目推送到 chat
,我会收到以下错误:
TypeError: Cannot read property '0' of null
也许我不太确定异步管道是如何工作的,但是当我尝试返回 {{ (chat | async).length }}
时,它会按预期工作。对 workaround/proper 练习有什么建议吗?
仍然不确定如何在此处操作 AsyncPipe,但我确实找到了一种不使用管道的解决方法。在将此标记为关闭之前,我希望等待更好的答案。
我订阅了我的class中的数据源,并在显示之前用for循环操作数组。
我问题中的(模板)代码现在变成了:
<div *ngFor='let message of messages; let i = index'>
<button *ngIf="message.isNewDay">
{{ message.timestamp | date:'ddMMM' }}
</button>
...
<!--More html elements below (omitted)-->
...
</div>
在控制器中:
private chatid: string //chat id passed from previous screen
private chat: FirebaseListObservable<any>;
private messages: any = [];
constructor(private firebase: FirebaseService,
private _datepipe: DatePipe) {
}
ionViewLoaded() {
this.chat = this.firebase.database.list('/chat-messages/' + this.chatid);
this.chat.subscribe((data) => {
this.messages = data;
for (let i: number = 0; i < this.messages.length; i++) {
if (i === 0)
this.messages[i].isNewDay = true;
else {
let date1 = this._datepipe.transform(this.messages[i].timestamp, 'ddMMMMyyyy');
let date2 = this._datepipe.transform(this.messages[i-1].timestamp, 'ddMMMMyyyy');
if (date1 !== date2)
this.messages[i].isNewDay = true;
else
this.messages[i].isNewDay = false;
}
}
});
}
请注意,我目前在 class 代码(以及模板)中使用 DatePipe,因此有必要将 providers: [DatePipe]
与 pipes: [DatePipe]
一起使用。
万一其他人发现这个,因为它是第一个带有关键字的结果,我能够像这样使用异步管道获得 *ngFor 的索引(假设 messages
是一个 Observable 的可迭代):
<div *ngFor="let message of (messages | async); let i = index;">
我使用一个函数来显示(或不显示)日期。因此,仅在日期更改时显示日期(在此示例中):
<ion-list no-lines>
<ion-item-sliding *ngFor="let trip of tripsExt$ | async; let i = index">
<ion-item>
<ion-row (click)="change(trip)">
<ion-col col-6>
{{showOnChange(trip.date)}}
</ion-col>
<ion-col col-6>
{{trip.end_address_name}}
</ion-col>
</ion-row>
</ion-item>
<ion-item-options side="left">
<button ion-button color="primary" (click)="delete(trip)">
Delete
</button>
</ion-item-options>
</ion-item-sliding>
</ion-list>
使用 showOnChange:
showOnChange(currentDate) {
if (currentDate != this.previousDate) {
this.previousDate = currentDate
return currentDate
}
return ''
}
正如@Primal Zed 上面提到的那样 let company of (filteredCompaniesAliases | async); let i = index"
应该可以解决问题,语法示例使用普通的 html table:
<table>
<tr *ngFor="let company of (filteredCompaniesAliases | async); let i = index"">
<td>
{{selectedDiscountableCharge.name}}
</td>
<td>
${{selectedDiscountableCharge.amount}}
</td>
<td>
${{selectedDiscountableCharge.amount - ( (selectedDiscountableChargePercentanges / 100) * selectedDiscountableCharge.amount ) }}
</td>
</tr>
</table>
在您的组件中:
companyAliasFilterCtrl: FormControl;
filteredCompaniesAliases: Observable<any[]>;
...
this.filteredCompaniesAliases = this.companyAliasFilterCtrl.valueChanges
.pipe(
startWith(''),
map(company => company ? this.filterOperatorsAliases(company) : this.companies.slice())
);
如果你想同时使用 *ngFor、AsyncPipe 和索引 - 你应该使用这种结构:
<ul>
<li *ngFor="let person of obsPersons | async as persons; index as i">
{{i + 1}} out of {{persons.length}}: {{person.personId}}
</li>
</ul>
已测试并适用于 Angular 7.
在上一个问题
区别在于我现在连接到一个实时数据库 (Firebase),所以我订阅了数据源并在通过索引和 *ngIf:
之前通过异步管道传递它<div *ngFor='let message of (chat | async) ; let i = index'>
<button *ngIf="i == 0 || (message.timestamp | date: 'ddMMMMyyyy') != ((chat | async)[i-1].timestamp | date: 'ddMMMMyyyy')">
{{ message.timestamp | date:'ddMMM' }}
</button>
...
<!--More html elements below (omitted)-->
...
</div>
这在我第一次加载视图时效果很好,但是,如果我将新条目推送到 chat
,我会收到以下错误:
TypeError: Cannot read property '0' of null
也许我不太确定异步管道是如何工作的,但是当我尝试返回 {{ (chat | async).length }}
时,它会按预期工作。对 workaround/proper 练习有什么建议吗?
仍然不确定如何在此处操作 AsyncPipe,但我确实找到了一种不使用管道的解决方法。在将此标记为关闭之前,我希望等待更好的答案。
我订阅了我的class中的数据源,并在显示之前用for循环操作数组。
我问题中的(模板)代码现在变成了:
<div *ngFor='let message of messages; let i = index'>
<button *ngIf="message.isNewDay">
{{ message.timestamp | date:'ddMMM' }}
</button>
...
<!--More html elements below (omitted)-->
...
</div>
在控制器中:
private chatid: string //chat id passed from previous screen
private chat: FirebaseListObservable<any>;
private messages: any = [];
constructor(private firebase: FirebaseService,
private _datepipe: DatePipe) {
}
ionViewLoaded() {
this.chat = this.firebase.database.list('/chat-messages/' + this.chatid);
this.chat.subscribe((data) => {
this.messages = data;
for (let i: number = 0; i < this.messages.length; i++) {
if (i === 0)
this.messages[i].isNewDay = true;
else {
let date1 = this._datepipe.transform(this.messages[i].timestamp, 'ddMMMMyyyy');
let date2 = this._datepipe.transform(this.messages[i-1].timestamp, 'ddMMMMyyyy');
if (date1 !== date2)
this.messages[i].isNewDay = true;
else
this.messages[i].isNewDay = false;
}
}
});
}
请注意,我目前在 class 代码(以及模板)中使用 DatePipe,因此有必要将 providers: [DatePipe]
与 pipes: [DatePipe]
一起使用。
万一其他人发现这个,因为它是第一个带有关键字的结果,我能够像这样使用异步管道获得 *ngFor 的索引(假设 messages
是一个 Observable 的可迭代):
<div *ngFor="let message of (messages | async); let i = index;">
我使用一个函数来显示(或不显示)日期。因此,仅在日期更改时显示日期(在此示例中):
<ion-list no-lines>
<ion-item-sliding *ngFor="let trip of tripsExt$ | async; let i = index">
<ion-item>
<ion-row (click)="change(trip)">
<ion-col col-6>
{{showOnChange(trip.date)}}
</ion-col>
<ion-col col-6>
{{trip.end_address_name}}
</ion-col>
</ion-row>
</ion-item>
<ion-item-options side="left">
<button ion-button color="primary" (click)="delete(trip)">
Delete
</button>
</ion-item-options>
</ion-item-sliding>
</ion-list>
使用 showOnChange:
showOnChange(currentDate) {
if (currentDate != this.previousDate) {
this.previousDate = currentDate
return currentDate
}
return ''
}
正如@Primal Zed 上面提到的那样 let company of (filteredCompaniesAliases | async); let i = index"
应该可以解决问题,语法示例使用普通的 html table:
<table>
<tr *ngFor="let company of (filteredCompaniesAliases | async); let i = index"">
<td>
{{selectedDiscountableCharge.name}}
</td>
<td>
${{selectedDiscountableCharge.amount}}
</td>
<td>
${{selectedDiscountableCharge.amount - ( (selectedDiscountableChargePercentanges / 100) * selectedDiscountableCharge.amount ) }}
</td>
</tr>
</table>
在您的组件中:
companyAliasFilterCtrl: FormControl;
filteredCompaniesAliases: Observable<any[]>;
...
this.filteredCompaniesAliases = this.companyAliasFilterCtrl.valueChanges
.pipe(
startWith(''),
map(company => company ? this.filterOperatorsAliases(company) : this.companies.slice())
);
如果你想同时使用 *ngFor、AsyncPipe 和索引 - 你应该使用这种结构:
<ul>
<li *ngFor="let person of obsPersons | async as persons; index as i">
{{i + 1}} out of {{persons.length}}: {{person.personId}}
</li>
</ul>
已测试并适用于 Angular 7.