Angular 订阅 EventEmitter 但获取现有项目
Angular subscribe to EventEmitter but fetch existing items
我正在尝试构建一个通知组件。为此,我需要通过服务向 NotificationComponent
发送通知。我这样做的方法是使用 EventEmitter 向组件发送通知,但我希望 NotificationComponent
在第一次通过订阅 Observable of Notifications 路由到现有通知时获取现有通知,但它不起作用。查看我的代码,请指出问题或建议替代方法。
目前只显示2号通知的通知(也就是说第一个通知没有到达NotificationComponent
但是2号到达)
下面是NotificationService的代码
import { Injectable } from '@angular/core';
import { Notification } from './notification';
import { from } from 'rxjs';
import { Router } from '@angular/router';
import { EventEmitter } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class NotificationService {
private notifications = [];
addEvent = new EventEmitter();
removeEvent = new EventEmitter();
constructor(private router: Router) {
}
add(title: string, message: string, expiresInSeconds: number = null) {
const noti = new Notification();
noti.title = title;
noti.message = message;
this.notifications.push();
this.addEvent.emit(noti);
this.router.navigate([{ outlets: {notification: 'notification'}}]);
if (expiresInSeconds > 0) {
setTimeout(() => {
this.removeById(noti.id);
}, expiresInSeconds * 1000);
}
}
/* get notifications */
getNotifications() {
return from(this.notifications);
}
/* remove a notification */
removeById(notificationId) {
const index = this.notifications.findIndex(n => {
return notificationId === n.id;
});
this.notifications.splice(index, 1);
this.removeEvent.emit(notificationId);
}
}
下面是NotificationComponent的代码class
import { Component, OnInit } from '@angular/core';
import { NotificationService } from '../notification.service';
import { Notification } from '../notification';
import { faWindowClose } from '@fortawesome/free-solid-svg-icons';
import { Router } from '@angular/router';
@Component({
selector: 'app-notifications',
templateUrl: './notifications.component.html',
styleUrls: ['./notifications.component.scss']
})
export class NotificationsComponent implements OnInit {
notifications: Notification[] = [];
faWindowClose = faWindowClose;
constructor(private ns: NotificationService,
private router: Router) {
}
ngOnInit() {
this.ns.getNotifications()
.subscribe(notifications => {
this.notifications = notifications;
});
this.ns.addEvent
.subscribe((notification => {
this.notifications.push(notification);
}));
this.ns.removeEvent
.subscribe((notification => {
const index = this.notifications.findIndex(n => {
return n.id === notification.id;
});
this.notifications.splice(index, 1);
}));
}
removeNotification(id) {
this.ns.removeById(id);
if (this.notifications.length <= 0) {
this.router.navigateByUrl('/user-panel');
}
}
}
以下是NotificationComponent
的模板html
<div *ngIf="notifications.length >= 1"
class="notification d-flex flex-row-reverse p-0">
<div *ngFor="let n of notifications"
class="alert alert-dark mx-1 p-0">
<div class="d-flex flex-row p-0">
<div class="flex-item flex-grow-1">
<h5>{{n.title}}</h5>
</div>
<div class="flex-item">
<button class="btn btn-sm btn-secondary"
(click)="removeNotification(n.id)">
<fa-icon [icon]="faWindowClose"></fa-icon>
</button>
</div>
</div>
<div>{{n.message}}</div>
</div>
</div>
将 addEvent 转换为 ReplaySubject。您的组件在发出第一个通知后呈现,并且仅在第一个事件消失后才订阅事件。使用 ReplaySubject,您的组件应该获得第一个事件。
addEvent = new ReplaySubject(1);
似乎还有一个小错误
this.notifications.push();
没有通知被推送到数组,调用时会出错removeById
我正在尝试构建一个通知组件。为此,我需要通过服务向 NotificationComponent
发送通知。我这样做的方法是使用 EventEmitter 向组件发送通知,但我希望 NotificationComponent
在第一次通过订阅 Observable of Notifications 路由到现有通知时获取现有通知,但它不起作用。查看我的代码,请指出问题或建议替代方法。
目前只显示2号通知的通知(也就是说第一个通知没有到达NotificationComponent
但是2号到达)
下面是NotificationService的代码
import { Injectable } from '@angular/core';
import { Notification } from './notification';
import { from } from 'rxjs';
import { Router } from '@angular/router';
import { EventEmitter } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class NotificationService {
private notifications = [];
addEvent = new EventEmitter();
removeEvent = new EventEmitter();
constructor(private router: Router) {
}
add(title: string, message: string, expiresInSeconds: number = null) {
const noti = new Notification();
noti.title = title;
noti.message = message;
this.notifications.push();
this.addEvent.emit(noti);
this.router.navigate([{ outlets: {notification: 'notification'}}]);
if (expiresInSeconds > 0) {
setTimeout(() => {
this.removeById(noti.id);
}, expiresInSeconds * 1000);
}
}
/* get notifications */
getNotifications() {
return from(this.notifications);
}
/* remove a notification */
removeById(notificationId) {
const index = this.notifications.findIndex(n => {
return notificationId === n.id;
});
this.notifications.splice(index, 1);
this.removeEvent.emit(notificationId);
}
}
下面是NotificationComponent的代码class
import { Component, OnInit } from '@angular/core';
import { NotificationService } from '../notification.service';
import { Notification } from '../notification';
import { faWindowClose } from '@fortawesome/free-solid-svg-icons';
import { Router } from '@angular/router';
@Component({
selector: 'app-notifications',
templateUrl: './notifications.component.html',
styleUrls: ['./notifications.component.scss']
})
export class NotificationsComponent implements OnInit {
notifications: Notification[] = [];
faWindowClose = faWindowClose;
constructor(private ns: NotificationService,
private router: Router) {
}
ngOnInit() {
this.ns.getNotifications()
.subscribe(notifications => {
this.notifications = notifications;
});
this.ns.addEvent
.subscribe((notification => {
this.notifications.push(notification);
}));
this.ns.removeEvent
.subscribe((notification => {
const index = this.notifications.findIndex(n => {
return n.id === notification.id;
});
this.notifications.splice(index, 1);
}));
}
removeNotification(id) {
this.ns.removeById(id);
if (this.notifications.length <= 0) {
this.router.navigateByUrl('/user-panel');
}
}
}
以下是NotificationComponent
的模板html<div *ngIf="notifications.length >= 1"
class="notification d-flex flex-row-reverse p-0">
<div *ngFor="let n of notifications"
class="alert alert-dark mx-1 p-0">
<div class="d-flex flex-row p-0">
<div class="flex-item flex-grow-1">
<h5>{{n.title}}</h5>
</div>
<div class="flex-item">
<button class="btn btn-sm btn-secondary"
(click)="removeNotification(n.id)">
<fa-icon [icon]="faWindowClose"></fa-icon>
</button>
</div>
</div>
<div>{{n.message}}</div>
</div>
</div>
将 addEvent 转换为 ReplaySubject。您的组件在发出第一个通知后呈现,并且仅在第一个事件消失后才订阅事件。使用 ReplaySubject,您的组件应该获得第一个事件。
addEvent = new ReplaySubject(1);
似乎还有一个小错误
this.notifications.push();
没有通知被推送到数组,调用时会出错removeById