如何顺序创建动态组件的多个实例?

发布于 2025-01-16 22:14:58 字数 2203 浏览 4 评论 0原文

我有一个 SystemMessageService,它使用以下方法创建 SystemMessageComponent 的实例

createSystemMessage(message: string, vcr: ViewContainerRef, time: number = 4500, isErrorMessage: boolean = false, isWarningMessage: boolean = false, isSuccessMessage: boolean = false){
    let systemMessageCmpFactory = this.componentFactoryResolver.resolveComponentFactory(SystemMessageComponent);
    this.hostViewContainerRef = vcr;
    this.hostViewContainerRef.clear();
    this.systemMessageCmpRef = this.hostViewContainerRef.createComponent(systemMessageCmpFactory);
    this.systemMessageCmpRef.instance.message = message;
    this.systemMessageCmpRef.instance.timeUntilDestruction = time;
    this.systemMessageCmpRef.instance.isErrorMessage = isErrorMessage;
    this.systemMessageCmpRef.instance.isWarningMessage = isWarningMessage;
    this.systemMessageCmpRef.instance.isSuccessMessage = isSuccessMessage;
    this.closeSubMsg = this.systemMessageCmpRef.instance.closeMessage.subscribe(() => {
      this.closeSubMsg.unsubscribe();
      this.hostViewContainerRef.clear()
    })
  }

现在我在 SystemMessageService 中有一个通知程序,

private systemMessageNotifier$: Subject<string> = new Subject();
public systemMessageObs$ = this.systemMessageNotifier$.asObservable();
emitSystemMessage(systemMessage: string){
    this.systemMessageNotifier$.next(systemMessage);
}

它通知 app.component .ts 何时显示新的系统消息

@ViewChild('systemMessageHost', {read: ViewContainerRef}) systemMessageHost: ViewContainerRef;
  constructor(private systemMessageService: SystemMessagesService){

  }

  ngOnInit(): void {
    this.systemMessageService.systemMessageObs$.subscribe(systemMessage => {
      this.systemMessageService.createSystemMessage(systemMessage, this.systemMessageHost, 60*1000*60)
    })
  }

,但问题是如果按顺序发送,消息会重叠,例如,如果我在任何组件中调用以下内容,

this.systemMessageService.emitSystemMessage("Message1");
this.systemMessageService.emitSystemMessage("Message2");

我只会显示“Message2”,但我想显示“Message1”首先,如果用户关闭组件,然后应显示“Message2”。我将如何实施这个? SystemMessageComponent 可以通过超时或单击关闭按钮来关闭。

I have a SystemMessageService which creates instances of SystemMessageComponent using the following method

createSystemMessage(message: string, vcr: ViewContainerRef, time: number = 4500, isErrorMessage: boolean = false, isWarningMessage: boolean = false, isSuccessMessage: boolean = false){
    let systemMessageCmpFactory = this.componentFactoryResolver.resolveComponentFactory(SystemMessageComponent);
    this.hostViewContainerRef = vcr;
    this.hostViewContainerRef.clear();
    this.systemMessageCmpRef = this.hostViewContainerRef.createComponent(systemMessageCmpFactory);
    this.systemMessageCmpRef.instance.message = message;
    this.systemMessageCmpRef.instance.timeUntilDestruction = time;
    this.systemMessageCmpRef.instance.isErrorMessage = isErrorMessage;
    this.systemMessageCmpRef.instance.isWarningMessage = isWarningMessage;
    this.systemMessageCmpRef.instance.isSuccessMessage = isSuccessMessage;
    this.closeSubMsg = this.systemMessageCmpRef.instance.closeMessage.subscribe(() => {
      this.closeSubMsg.unsubscribe();
      this.hostViewContainerRef.clear()
    })
  }

Now I have a notifier in SystemMessageService,

private systemMessageNotifier$: Subject<string> = new Subject();
public systemMessageObs$ = this.systemMessageNotifier$.asObservable();
emitSystemMessage(systemMessage: string){
    this.systemMessageNotifier$.next(systemMessage);
}

which informs app.component.ts when to display a new system message

@ViewChild('systemMessageHost', {read: ViewContainerRef}) systemMessageHost: ViewContainerRef;
  constructor(private systemMessageService: SystemMessagesService){

  }

  ngOnInit(): void {
    this.systemMessageService.systemMessageObs$.subscribe(systemMessage => {
      this.systemMessageService.createSystemMessage(systemMessage, this.systemMessageHost, 60*1000*60)
    })
  }

but the problem is that messages would overlap if sent sequentially, for example if I call the following in any component

this.systemMessageService.emitSystemMessage("Message1");
this.systemMessageService.emitSystemMessage("Message2");

I would only show "Message2" but I want to show "Message1" first and if the user closes the component, then "Message2" should be shown afterwards. How would I implement this? The SystemMessageComponentcan be closed either by timeout or click on a close button.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

灯下孤影 2025-01-23 22:14:58

我这样解决了:我使用一个变量来检查实例是否存在。如果存在,我将下一条消息推送到数组中。当实例被销毁时,我使用通知程序来通知 app.component 该实例已被销毁,以便如果有另一条消息,则可以显示下一条消息。

private systemMessageNotifier$: Subject<SystemMessage> = new Subject();
public systemMessageObs$ = this.systemMessageNotifier$.asObservable();
private sysMsgDestroyedNotifier$: Subject<any> = new Subject();
public systemMessageDestroyed$ = this.sysMsgDestroyedNotifier$.asObservable();

createSystemMessage(message: string, vcr: ViewContainerRef, messageType: SystemMessageType, noTimeOut: boolean = false, timeUntilDestruction: number = 1000*3600){
    let systemMessageCmpFactory = this.componentFactoryResolver.resolveComponentFactory(SystemMessageComponent);
    this.hostViewContainerRef = vcr;
    this.hostViewContainerRef.clear();
    this.systemMessageCmpRef = this.hostViewContainerRef.createComponent(systemMessageCmpFactory);
    this.systemMessageCmpRef.instance.message = message;
    this.systemMessageCmpRef.instance.timeUntilDestruction = timeUntilDestruction;
    this.systemMessageCmpRef.instance.messageType = messageType;
    this.systemMessageCmpRef.instance.noTimeOut = noTimeOut;
    this.closeSubMsg = this.systemMessageCmpRef.instance.closeMessage.subscribe(() => {
      this.closeSubMsg.unsubscribe();
      this.hostViewContainerRef.clear();
      this.sysMsgDestroyedNotifier$.next();
    })
  }
export class AppComponent implements OnInit {
  delayedSystemMessages = [];
  isSystemMessageComponentActive: boolean = false; 
  @ViewChild('systemMessageHost', {read: ViewContainerRef}) systemMessageHost: ViewContainerRef;
  constructor(private systemMessageService: SystemMessagesService){

  }

  ngOnInit(): void {
    
    this.systemMessageService.systemMessageDestroyed$.subscribe(() => {
      if(this.delayedSystemMessages.length > 0){
        this.isSystemMessageComponentActive = false;
        let message = this.delayedSystemMessages.shift()
        this.systemMessageService.emitSystemMessage(message);
      }
    })

    this.systemMessageService.systemMessageObs$.subscribe(systemMessage => {
      if(this.isSystemMessageComponentActive){
        this.delayedSystemMessages.push(systemMessage)
        return;
      }
      this.isSystemMessageComponentActive = true;
      this.systemMessageService.createSystemMessage(systemMessage.message, this.systemMessageHost, systemMessage.messageType, systemMessage.noTimeOut, systemMessage.timeUntilDestruction)
    })
  }
}

I solved it this way: I use a variable to check whether an instance exists. If it exists I push the next message in an array. When the instance is destroyed, I use a notifier to inform app.component that the instance was destroyed so that, if there is another message, the next message can be shown.

private systemMessageNotifier$: Subject<SystemMessage> = new Subject();
public systemMessageObs$ = this.systemMessageNotifier$.asObservable();
private sysMsgDestroyedNotifier$: Subject<any> = new Subject();
public systemMessageDestroyed$ = this.sysMsgDestroyedNotifier$.asObservable();

createSystemMessage(message: string, vcr: ViewContainerRef, messageType: SystemMessageType, noTimeOut: boolean = false, timeUntilDestruction: number = 1000*3600){
    let systemMessageCmpFactory = this.componentFactoryResolver.resolveComponentFactory(SystemMessageComponent);
    this.hostViewContainerRef = vcr;
    this.hostViewContainerRef.clear();
    this.systemMessageCmpRef = this.hostViewContainerRef.createComponent(systemMessageCmpFactory);
    this.systemMessageCmpRef.instance.message = message;
    this.systemMessageCmpRef.instance.timeUntilDestruction = timeUntilDestruction;
    this.systemMessageCmpRef.instance.messageType = messageType;
    this.systemMessageCmpRef.instance.noTimeOut = noTimeOut;
    this.closeSubMsg = this.systemMessageCmpRef.instance.closeMessage.subscribe(() => {
      this.closeSubMsg.unsubscribe();
      this.hostViewContainerRef.clear();
      this.sysMsgDestroyedNotifier$.next();
    })
  }
export class AppComponent implements OnInit {
  delayedSystemMessages = [];
  isSystemMessageComponentActive: boolean = false; 
  @ViewChild('systemMessageHost', {read: ViewContainerRef}) systemMessageHost: ViewContainerRef;
  constructor(private systemMessageService: SystemMessagesService){

  }

  ngOnInit(): void {
    
    this.systemMessageService.systemMessageDestroyed$.subscribe(() => {
      if(this.delayedSystemMessages.length > 0){
        this.isSystemMessageComponentActive = false;
        let message = this.delayedSystemMessages.shift()
        this.systemMessageService.emitSystemMessage(message);
      }
    })

    this.systemMessageService.systemMessageObs$.subscribe(systemMessage => {
      if(this.isSystemMessageComponentActive){
        this.delayedSystemMessages.push(systemMessage)
        return;
      }
      this.isSystemMessageComponentActive = true;
      this.systemMessageService.createSystemMessage(systemMessage.message, this.systemMessageHost, systemMessage.messageType, systemMessage.noTimeOut, systemMessage.timeUntilDestruction)
    })
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文