简体   繁体   English

Angular 组件无法使用@Input 和服务正确更新

[英]Angular component does not update correctly using @Input and a Service

I'm using Angular version 7 with a component that has a serie of divs being rendering according to the data coming from an @Input and it should be updated due the service response, nevertheless the component is not correctly updated, the loader remains loading ( loading=true ) until I click into the text input and then I click elsewhere.我正在使用 Angular 版本 7 和一个组件,该组件具有根据来自@Input的数据呈现的一系列 div 并且它应该由于服务响应而更新,但是组件没有正确更新,加载器仍在加载( loading=true ) 直到我单击文本输入,然后单击其他位置。

Template:模板:

<div class="row" *ngFor="let message of messages">
  <div>{{message.date}}</div>
  <div>{{message.body}}</div>
</div>
<div class="row" *ngIf="thread.isOpen">
  <div class="panel" >
    <form (ngSubmit)="onSubmit()" [formGroup]="messageForm">
      <textarea class="textarea" name="message" id="message" formControlName="message"></textarea>
      <button class="btn"">
      <span *ngIf="!loading; else loadingTemplate">send</span>
      <ng-template #loadingTemplate>
        <i class="fa fa-spin"></i>
      </ng-template>
    </button>
 </form>
</div>

Component:零件:

@Input() messages;
messageForm: FormGroup;
loading: boolean = false;

ngOnInit(): void {
    this.loadFromControls();
}

loadFromControls(): void {
  this.messageForm = this.formBuilder.group({
    message: this.formBuilder.control('', [])
  });
}

onSubmit() {
  if (!this.messageForm.valid) return;
    this.loading = true;
    const message = this.messageForm.controls['message'].value;
  
    this.service.sendMessage(this.thread._id, message).subscribe(() => {
      if (this.messages) {
        this.messages.push({
            isFromExtranet: true,
            date: new Date(),
            body: message
        });
      }

      this.messageForm.controls['message'].setValue("");
      this.loading = false;
    }, (err) => this.errorMessage(err));
  }

Service服务

sendMessage(id: string, message: string): Observable<any> {
  return this.http.post(`/api/messages/${id}`, { message })
        .map((res) => res.json())
        .catch((error) => Observable.throw(error.json().code || 'error'));
}

I've been dealing with this a few hours and maybe I'm just missing something very basic.我已经处理了几个小时,也许我只是错过了一些非常基本的东西。

Can you try update the code as per below and make sure that you're getting correct value from @Input decorator.您可以尝试按照以下方式更新代码,并确保您从 @Input 装饰器中获得正确的值。

<div *ngIf="isDataloaded>    
<div class="row" *ngFor="let message of messages">
      <div>{{message.date}}</div>
      <div>{{message.body}}</div>
    </div>
    <div class="row" *ngIf="thread.isOpen">
      <div class="panel" >
        <form (ngSubmit)="onSubmit()" [formGroup]="messageForm">
          <textarea class="textarea" name="message" id="message" formControlName="message"></textarea>
          <button class="btn"">
          <span *ngIf="!loading; else loadingTemplate">send</span>
          <ng-template #loadingTemplate>
            <i class="fa fa-spin"></i>
          </ng-template>
        </button>
     </form>
    </div>
</div> 

Component.ts组件.ts

 @Input() messages;
    isDataloaded = flase;
    messageForm: FormGroup;
    loading: boolean = false;
    
    ngOnInit(): void {
        this.loadFromControls();
    }
    
    loadFromControls(): void {
      this.messageForm = this.formBuilder.group({
        message: this.formBuilder.control('', [])
      });
    }
    
    onSubmit() {
      this.loading = true;
      if (!this.messageForm.valid) return;
        const message = this.messageForm.controls['message'].value;
      
        this.service.sendMessage(this.thread._id, message).subscribe(() => {
          if (this.event.data.discussionThread.messages) {
            this.event.data.discussionThread.messages.push({
                isFromExtranet: true,
                date: new Date(),
                body: message
            });
          }
    
          this.messageForm.controls['message'].setValue("");
          this.loading = false;
        }, (err) => this.errorMessage(err));
         this.isDataloaded = true;
      }

I fixed using a BehaviorSubject , as:我使用BehaviorSubject进行了修复,如下所示:

loading$: BehaviorSubject<boolean> = new BehaviorSubject(false);
...
this.loading$.next(true);

instead of:代替:

loading: boolean = false;
...
this.loading = true;

and in the template with async as:并在模板中异步为:

<span *ngIf="!(loading$ | async); else loadingTemplate">

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM