Angular 6-带有可注射服务的跨组件通信

时间:2019-01-16 21:05:12

标签: javascript angular typescript

我已经为此工作了几天,却没有发现任何对我有帮助的东西,所以我终于问了。

我有2个子组件,1个父组件和1个服务。目前,该服务将处理我所有对后端nodejs的http请求,而这些请求均正常运行。我遇到麻烦的只是客户端。

很抱歉,有很多代码,但是如果我没有全部包括在内,这是没有意义的。

这是组件的打字稿代码,该组件执行初始触发器以发出http请求。所以一个按钮运行runAutoClose()

runAutoClose() {

this.AppSub = this.appServices.procesAutoClose()
.subscribe((postMessages: Message[])=>{
  if(postMessages.length>1) postMessages.splice(0,1);
  //send event to parent company and pass the new postMessage
  this.sendAlert.emit(postMessages.slice(-1).pop());
})

}

这是服务。

@Injectable({
providedIn: 'root'
})

export class AppServices {
private messages: Message[] = [];
private messagesUpdated = new Subject<Message[]>();
private ticketOptions: Tickets[] = [];

constructor(private http: HttpClient) {
}//inject the HttpClien to this service. Bind the HttpClient class to the http property to use in this service

get messageUpdated(): any { return this.messagesUpdated;}


private handleError(error: HttpErrorResponse) {
    let errorMessage = '';
    if (error.error instanceof ErrorEvent) {
        errorMessage = error.error.message;
    } else {
        errorMessage = `Backened Error: ${error.status}, ${error.error.message}`;
    }
    return throwError(errorMessage);
};

procesAutoClose() {
    this.executeAutoClose()
    return this.messagesUpdated.asObservable();  
}

executeAutoClose() {

        this.http
        .get<{message: any}>('http://localhost:3000/api/posts')
        .subscribe((postMessages: any)=>{
            console.log(postMessages);
            this.messages.splice(0,1);               
            this.messages.push(postMessages);
            this.messagesUpdated.next([...this.messages]);              
        })       
}
}

这是消息警报组件,它将最终来自后端的任何警报/消息输出到屏幕。

  export class AlertMessageComponent implements OnInit, OnDestroy {
  @Output() closeAlert = new EventEmitter();
  @Input() index = '';
  @Input('alertElement') element: {
    type: string,
    name: string,
    content: string
  }
  subscription: Subscription;
  constructor(appServices: AppServices) {
    this.appServices = appServices;
   }

  appServices: AppServices;

  ngOnInit() {
    this.subscription = this.appServices.messageUpdated.subscribe((message)=>{
      this.element = message;
    })
  }

  ngOnDestroy():void {
    console.log('here')
    //this.subscription.unsubscribe();
  }

  removeAlertComponent(){   
    this.closeAlert.emit(this.index);
  }

}

这是app.component.html,以显示我如何绑定到属性和侦听事件。

<!--the ticket function that makes original event trigger selector-->
  <app-ticket-function 
  *ngIf="loadedFeature === 'tickets'"
  (showProgress)="showProgressBar($event)" 
  (executeAutoClose)="runAutoCloseBack()" 
  (executeUpdatedTickets)="runUpdatedTickets()"
  (sendAlert)="updateAlert($event)">
  </app-ticket-function>

  <app-update-steps 
  *ngIf="loadedFeature === 'updSteps'"></app-update-steps>
  <app-member-code *ngIf="loadedFeature === 'members'"></app-member-code>

  <app-progress-bar *ngIf="showProgress"></app-progress-bar>
  <!--the message alert component-->
  <app-alert-message *ngFor="let alertElement of alertElements; index as i" [index]="i" [alertElement]="alertElement" (closeAlert)="destroyAlert($event)"></app-alert-message>

这是app.component.ts文件中从app.component.html调用的2种方法。

    destroyAlert(index) {

    this.appServices.messageUpdated.unsubscribe();
    this.alertElements.splice(index, 1)
  }

  updateAlert(alert:any) {
    console.log(alert);
    this.alertElements.push(alert);
    console.dir(this.alertElements);
  }

我想做的是将服务中定义的messagesUpdated属性数组作为每个消息的新组件发送到alert-message.component。这些消息将显示在我其他组件下方的屏幕上。

我已经做了一些事情来解决我遇到的所有问题,现在当我关闭警报时,它正在取消订阅messageUpdated主题。这是在上面的destroyAlert()函数中。问题是,当我取消订阅该主题时,下次单击屏幕上的按钮来运行该服务时,会出现此错误

ObjectUnsubscribedErrorImpl {message: "object unsubscribed", name: 
"ObjectUnsubscribedError"}
message: "object unsubscribed"
name: "ObjectUnsubscribedError"
__proto__: Error

我猜是因为该主题不再存在。如果它不存在,也许我可以以某种方式再次创建它??

我想到了许多不同的选择,但我无能为力。

或者删除警报,然后以某种方式告诉该服务从该订阅中删除该特定消息对象,而不是取消整个订阅。也许在Message []数组上有一个索引属性,我可以在服务的函数中将其传递以删除它?

最初,最初发生的是将消息插入到该订阅中并且没有被删除,因此,每当我单击表单上的按钮时,下一次警报组件显示消息时,对象数量就会增加一倍在那个数组里面。这就是为什么我拥有上面所有的.splices()似乎都不起作用的原因。

我当然愿意接受新的建议,因为我什至没有尽我所能实现的最佳方法。我对Angular相当陌生,所以希望您了解我的无知。 基本上目标是:

  1. 单击按钮以发出http请求。 (有效)

  2. 从后端获取消息并以某种方式存储,以显示为警报消息框。

  3. 单独关闭警报时,不应影响屏幕上的其他消息警报。如果发出新请求,它只会添加到屏幕上显示的警报数组中。

感谢所有帮助!

0 个答案:

没有答案