【问题标题】:Angular not updating view after data has been updated数据更新后角度不更新视图
【发布时间】:2020-12-17 04:16:57
【问题描述】:

我有两个组件。一种用于创建,另一种用于列出存储在数据库中的数据。 问题是,当我创建一个存储在数据库中的新数据库时,我尝试告诉“lister”更新其视图,以便它可以显示刚刚添加的内容。奇怪的是它没有显示出来,即使我看到它自己的数据已经更新并从数据库加载,但没有显示组件的视图。 在这里稍微精简了代码。

“创造者”

import { Component, Inject, Input } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { DataService } from '../../data.service';
import { DataRestaurant } from '../../shared/data/restaurant';

import { ModulesRestaurants } from './restaurants.moldule';


@Component({
  selector: 'app-module-make-restaurant',
  templateUrl: './make.restaurant.module.html',
  providers: [ModulesRestaurants]
})
export class ModulesMakeRestaurant {

  @Input() restaurantData = { name: '', description: '' };
  restaurant: DataRestaurant;

  constructor(private dataService: DataService, private translate: TranslateService, private restLister: ModulesRestaurants) {
       translate.setDefaultLang('en');
  }

  ngOnInit() {
    this.restaurant = new DataRestaurant;
  }


  // Create restaurant - used by the button the makes the new data
  createRestaurant() {
    this.dataService.createRestaurant(this.restaurantData).subscribe(data => {
      this.restLister.refresh();  //Calls the 'refresh' in the lister
    });
  }
}

“听者”

import { Component, Inject, Input, Injectable, ViewChild, ApplicationRef  } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { DataService } from '../../data.service';
import { DataRestaurant } from '../../shared/data/restaurant';



@Component({
  selector: 'app-module-restaurants',
  templateUrl: './restaurants.module.html'
})


export class ModulesRestaurants {

  @Input() restaurantData = { name: '', description: '', };

  DataRestaurants: any = [];


  constructor(private dataService: DataService, private translate: TranslateService private appRef: ApplicationRef) {
    translate.setDefaultLang('en');
  }

  ngOnInit() {
    this.getAll();

  }


  refresh() {
    this.getAll();
    this.appRef.tick();

  }

  // Get all restaurants
  getAll() {
    return this.dataService.getAllRestaurants().subscribe((data: {}) => {
      this.DataRestaurants = data;
      console.log(this.DataRestaurants);
    })
  }



  trackData(index: number, item: DataRestaurant) {
    return this.DataRestaurants ? this.DataRestaurants : undefined;
  }

}

数据库服务

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { DataRestaurant } from '../app/shared/data/restaurant';
import { Observable, throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';
import { Guid } from "guid-typescript";

@Injectable({
  providedIn: 'root'
})
export class DataService {

  private REST_API_SERVER = "https://localhost:44377/api";

  constructor(private http: HttpClient) { }


  // Http Options
  httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    })
  } 


  ////RESTAURANTS
  //HttpClient API post() method => Get all restaurants
  getAllRestaurants(): Observable<any> {
    return this.http.get<DataRestaurant[]>(this.REST_API_SERVER + '/restaurant/GetAll')
      .pipe(
        retry(1),
        catchError(this.handleError<DataRestaurant[]>('getAllRestaurants'))
      )
  }

  // HttpClient API post() method => Create restaurant
  createRestaurant(data): Observable<any> {
    return this.http.post<DataRestaurant>(this.REST_API_SERVER + '/restaurant/Create', JSON.stringify(data), this.httpOptions)
      .pipe(
        retry(1),
        catchError(this.handleError<DataRestaurant>('createRestaurants'))
      )
  }

    // HttpClient API delete() method => Delete restaurant
  deleteRestaurant(id): Observable<any> {
    return this.http.delete<DataRestaurant>(this.REST_API_SERVER + '/restaurant/Delete/' + id, this.httpOptions)
      .pipe(
        retry(1),
        catchError(this.handleError<DataRestaurant>('deleteRestaurant'))
      )
  }

  // Error handling
  private handleError<T>(operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {
    
      console.error(error);

      return throwError(result as T);
    };
  }


}

HTML 列表器

  <ng-container>
      <table>
        <thead class="text-primary">
          <tr>
            <th scope="col">{{ 'restaurants.name' | translate }}</th>
            <th scope="col"></th>
          </tr>
        </thead>
        <tbody">
          <tr *ngFor="let data of DataRestaurants; let i = index; trackBy: trackData" >
            <td>
              <input type="text"
                     [(ngModel)]="data.name"
                     class="form-control"
                     placeholder="Name"
                     style="outline:none;">
            </td>
          </tr>
        </tbody>
      </table>
      <div class="row">
        <div class="update">
          <button type="button" class="btn btn-primary btn-round" (click)="getAll()"> Refresh </button>
        </div>
      </div>

  </ng-container>

就像我提到的 refresh() 作品并从“制造商”那里得到调用。我什至可以看到this.DataRestaurants 已使用新数据进行了更新。但它没有在视图中更新。

更新: 在进行了更多调试之后,我得出结论,似乎有两个相同数据的实例。显示的一个,以及制造商的“刷新”调用使用的一个。 [providers] 不是在初始化的同一线程上运行吗?

这里有什么建议吗?

【问题讨论】:

  • 我怀疑这与您的 trackBy 函数有关。你真的需要吗?如果您真的被卡住并且无法更新绑定,您可以将ChangeDetectorRef 注入您的组件并在分配字段后调用DetectChanges 方法。但这确实应该是最后的手段。
  • 这似乎更多地与实例有关,因为在检查应该更新的数据之前和之后进行了更多的调试。我可以看到 Maker getAll() 数据与 getAll() 在 Lister 上运行时的数据不同。

标签: angular typescript angular-services angular-components


【解决方案1】:

首先,Lister 组件应该只接收餐厅数据。这提供了一个很好的智能 - 哑组件结构并删除了不必要的注入。

父组件

refresh$ = new Subject(); // a button can call refresh$.next() and it will retrieve the data again
restaurantData$ = this.getAll();

getAll() {
 return this.refresh$.pipe(
   startWith(<unknown>null),
   switchMap(()=> this.dataService.getAllRestaurants())
 );

}

在模板中使用 restaurantData$|异步

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-02
    • 2015-01-07
    • 1970-01-01
    • 2015-06-26
    • 2017-11-11
    相关资源
    最近更新 更多