Таблица материалов не обновляется с новыми значениями @Input

#angular #typescript #angular-material #angular-material-table

#angular #typescript #angular-material #таблица угловых материалов

Вопрос:

У меня есть угловой компонент, который принимает @Input (результат поиска), который я хочу использовать в качестве источника данных таблицы угловых материалов.

К сожалению, таблица, похоже, не распознает, когда переменная @Input изменяется, и всегда остается пустой.

Мой рабочий процесс таков:

  • основное представление состоит из 2 компонентов: search и search-result .
  • search определяет параметры поиска и получает результат от searchservice.
  • поиск уведомляет main о том, что у него есть новый результат, и main сохраняет результат в переменной.
  • search-result получает переменную как @Input и обновляет таблицу результатами.

Все работает до console.log(this.passengerSearchReadModels); тех пор, пока не будет выведен правильный результат, но последний шаг (обновление таблицы) не выполняется: (

main.html

 <div class="mx-5">
  <app-search (notify)="onSearch($event)"></app-search>
  <app-search-result [passengerSearchReadModels]="passengerSearchReadModels"></app-search-result>
</div>
  

main.ts

 @Component({
  selector: 'app-main',
  templateUrl: './main.component.html',
  styleUrls: ['./main.component.scss']
})
export class MainComponent implements OnInit {

  passengerSearchReadModels: PassengerSearchReadModel[] = [];

  constructor() { }

  ngOnInit(): void {
  }

  onSearch(passengerSearchReadModels: PassengerSearchReadModel[]): void {
    console.log('in onSearch');
    this.passengerSearchReadModels = passengerSearchReadModels;
    console.log(this.passengerSearchReadModels); // here the correct result is displayed in the console
  }
}
  

search.ts

 @Component({
  selector: 'app-search',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.scss']
})
export class SearchComponent implements OnInit {
  @Output() notify: EventEmitter<PassengerSearchReadModel[]> = new EventEmitter<PassengerSearchReadModel[]>();

  searchQuery: SearchQuery;
  passengerSearchReadModels: PassengerSearchReadModel[] = [];

  constructor(private searchService: SearchService) {
    this.searchQuery = {
      lastName: null
    };

    this.init();
  }

  ngOnInit(): void {
  }

  init(): void {
  }

  search(): void {
    this.searchService.getPassengers(this.searchQuery)
      .subscribe(result => {
        console.log(result);
        this.passengerSearchReadModels.push(result);
      }, error => console.error(error));

    this.notify.emit(this.passengerSearchReadModels);
  }
}
  

search-result.html:

 <table mat-table [dataSource]="dataSource" matSort>
   <ng-container matColumnDef="fullName">
   <th mat-header-cell *matHeaderCellDef mat-sort-header>Name, Vorname</th>
   <td mat-cell *matCellDef="let element">{{element.lastName}}, {{element.firstName}}</td>
   </ng-container>

   <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
   <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
  

search-result.ts

 @Component({
  selector: 'app-search-result',
  templateUrl: './search-result.component.html',
  styleUrls: ['./search-result.component.scss']
})
export class SearchResultComponent implements AfterViewInit {
  @Input() passengerSearchReadModels: PassengerSearchReadModel[] = [];

  @ViewChild(MatSort, { static: true }) sort: MatSort;

  displayedColumns: string[] = [ColumnNames.FullName];

  dataSource = new MatTableDataSource<PassengerSearchReadModel>(this.passengerSearchReadModels);
  selection = new SelectionModel<PassengerSearchReadModel>(true, []);

  constructor() {
  }

  ngAfterViewInit(): void {
    this.dataSource.sortingDataAccessor = this.sortingDataAccessor;
    this.dataSource.sort = this.sort;
  }

// sorting deleted bc irrelevant
}
  

#Редактировать
search.html

 <div class="shadow">
  <div class="row">

    <div class="col-2">
      <mat-form-field>
        <mat-label>{{ "search.lastname" | translate }}</mat-label>
        <input matInput type="text" max="100" [(ngModel)]="searchQuery.lastName" />
      </mat-form-field>
    </div>
   
  </div>
<div class="row">
    <div class="col-3">
      <button mat-stroked-button color="primary" (click)="search()">
        <span class="material-icons mr-2">search</span>
        {{ "search.searchButton" | translate }}
      </button>
    </div>
    <div class="col-3"></div>
  </div>
</div>
  

SearchService.ts

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

  private ENDPOINT_GET = 'Passenger';

  constructor(private http: HttpClient) { }

  public getPassengers(searchQuery: SearchQuery): Observable<PassengerSearchReadModel> {
    let params = new HttpParams();
    if (searchQuery.lastName) { params = params.append('lastName', searchQuery.lastName); }
 
    return this.http.get<PassengerSearchReadModel>(environment.API_URL   this.ENDPOINT_GET, { params });
  }
}
  

this.sortingDataAccessor

 sortingDataAccessor(item: any, property: string): any {
    const columnSortingDataAccessors = ColumnSortingDataAccessor.get();
    let sortingDataAccessor: string;
    switch (property) {
      // cases omitted for readability
      default: {
        sortingDataAccessor = columnSortingDataAccessors[property];
        break;
      }
    }

    return item[sortingDataAccessor];
  }
  

Что мне нужно изменить, чтобы таблица обновлялась с новыми значениями?

Комментарии:

1. search.html , this.SearchService.getPassengers и this.sortingDataAccessor отсутствуют в вашем запросе. можете изменить ваш вопрос, чтобы я мог исправить проблему для вас

2. привет, @ZulqarnainJalil, я добавил код для того, что вы просили

Ответ №1:

Я нашел несколько проблем в вашем коде, сначала вам нужно выдать результат после загрузки результата, как в приведенном ниже коде

 search(): void {
    this.searchService.getPassengers(this.searchQuery)
      .subscribe(result => {
       this.notify.emit(result );
      }, error => console.error(error));    
  }
  

во-вторых, вам нужно инициализировать новый источник таблицы каждый раз при изменении данных, или вам просто нужно изменить источник данных таблицы данных (mat-table)

 onSearch(passengerSearchReadModels): void {
   this.passengerSearchReadModels = new MatTableDataSource<any>(passengerSearchReadModels);
  }
  

или

  onSearch(passengerSearchReadModels): void {
   this.passengerSearchReadModels.data = passengerSearchReadModels;
 }
  

вы можете проверить демонстрацию здесь

Комментарии:

1. да, круто, что сработало, большое вам за это спасибо! 🙂