Having trouble organizing data using matSort in conjunction with API information

Everything was running smoothly with my mat-table until I tried adding mat-sort as per the official API documentation. Unfortunately, it failed at ngAfterViewInit with the following error message:

ERROR TypeError: Cannot set property 'sort' of undefined

Check out this screenshot for the first error .. Not sorting

Despite the data being correctly displayed from the API, I attempted to move the code to the component's constructor to only set this in the onInit:

this.listData.sort = this.sort;

I made sure to import the module in the app.module.

Here are the contents of my three files:

Componenet.html

<mat-table [dataSource]="listData" matSort>
    <ng-container matColumnDef="gender">
      <mat-header-cell *matHeaderCellDef mat-sort-header>Gender</mat-header-cell>
      <mat-cell *matCellDef="let element">{{element.gender}}</mat-cell>
    </ng-container>
    <ng-container matColumnDef="firstname">
      <mat-header-cell *matHeaderCellDef mat-sort-header>First Name</mat-header-cell>
      <mat-cell *matCellDef="let element">{{element.firstname}}</mat-cell>
    </ng-container>

component.ts

import {AfterViewInit, Component, OnInit, ViewChild} from '@angular/core';
import {PersonneService} from '../../shared/personne.service';
import { MatTableDataSource, MatSort} from '@angular/material';
import {Personne} from '../../personne';

@Component({
  selector: 'app-personne-list',
  templateUrl: './personne-list.component.html',
  styleUrls: ['./personne-list.component.css']
})
export class PersonneListComponent implements AfterViewInit {

  personne: any = [];
  constructor(private service: PersonneService) {
    this.service.getPersonnes().subscribe((data: {}) => {
      this.personne = data;
      this.listData = new MatTableDataSource(this.personne);
    });
  }

  listData: MatTableDataSource<Personne>;
  displayedColumns: string[] = ['gender', 'firstname', 'lastname', 'address', 'city', 'state', 'ordertotal', 'actions'];

  @ViewChild(MatSort) sort: MatSort;
  ngAfterViewInit() {
    console.log({SORT: this.sort});
    this.listData.sort = this.sort;
  }

}

Service.ts :

import { Injectable } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import {Personne} from '../personne';
import {Observable} from 'rxjs';
import {map} from 'rxjs/operators';


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

  constructor(private http: HttpClient) {}
  
  // More service methods here

  getPersonnes() {
    return this.http.get('http://localhost:3000/api/personnes');
  }

While researching this issue, I stumbled upon this answer on Stack Overflow:

To address the issue, I added the following line to the html:

[hidden]="!listData.data" matSort

Now, when I click to sort, it does so but not accurately, and I encounter another error in the console:

ERROR TypeError: Cannot read property 'data' of undefined

Here's a screenshot for the second error

Your assistance in resolving this would be greatly appreciated.

Answer №1

Shift this particular line

    this.listData.sort = this.sort;

from its current placement within ngAfterViewInit to a point after you have successfully received and processed the data from getPersonnes(). Specifically, move it to this section:

    this.service.getPersonnes().subscribe((data: {}) => {
      this.personne = data;
      this.listData = new MatTableDataSource(this.personne);
      this.listData.sort = this.sort;
    });

To resolve the issue of

ERROR TypeError: Cannot read property 'data' of undefined
, simply utilize the safe navigation operator.

In the code snippet

<mat-table [dataSource]="listData" [hidden]="!listData.data" matSort>
, modify it to [hidden]="!listData?.data". By doing so, the script will only attempt to access listData.data when listData is actually defined.

Answer №2

When I encountered this issue, I couldn't find any working examples to solve it. Eventually, I resorted to using a setTimeout function to delay setting the paginator and sorting functionality like so:

this.employeeService.getAllEmployees().subscribe((employees: Employee[]) => {
  this.datasource = new MatTableDataSource<Employee>(employees)
  setTimeout(() => {
    this.datasource.paginator = this.paginator;
    this.datasource.sort = this.sort
  })
  this._isLoading.next(false)
})

It may not be the most elegant solution, but it did resolve my problem!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to delay a recursive JavaScript function for 3 seconds?

Before writing this post, I have already come across the following questions: how-to-pause-a-settimeout-call how-to-pause-a-settimeout-function how-to-pause-a-function-in-javascript delay-running-a-function-for-3-seconds Question The below code snipp ...

Adjusting the transparency of TabBadge in Ionic 2

I am currently working on a project that involves tabs, and I'm looking to update the style of the badge when the value is 0. Unfortunately, I am unsure how to dynamically change the style of my tabs or adjust the opacity of the badge in the style. M ...

I encountered an issue with my autocomplete feature in Angular TypeScript where it was returning a [object Object] value

Issue with autocomplete displaying [object Object] value in Angular TypeScript I'm having trouble pinpointing the exact problem HTML snippet <mat-form-field style="margin-right: 10px;"> <input #productName matInput placeholder="Product" ...

Uncover the content of a base64 encoded string and convert it into

A JSON response has been linked on the user's request to retrieve an excel document. The structure of the response is as follows: { "format": // file extn ----only xls "docTitle": //file name "document" :// base 64 encoded data } The attem ...

Managing multiple Sequelize DB connections in NestJS: A guide

I recently came across the example in the NestJS documentation regarding setting up a Sequelize DB connection. I'm curious about how to connect to multiple databases using Sequelize and TypeScript with NestJS. Can anyone provide guidance on this? ...

Guide on utilizing async/await in .ts files (Encountering error message: "async functions can only be used when targeting ECMAScript 6 or above")

Initially, my project consisted of only app.js using ExpressJS as the main file with numerous lines of code. My development manager instructed me to refactor the code and move some functions into a separate .ts file (transition from JavaScript to TypeScrip ...

Steps to resolve the issue of 'type is not assignable to any' while working with a member

I'm facing an issue with a code snippet like the one below: interface IFoo { bar: string; baz: number; } function f(foo: IFoo, name: 'bar' | 'baz', val: any) { foo[name] = val; // <<< error: Type 'any' i ...

When the frontend-maven-plugin executes the npm run build command, it encounters difficulty locating the package.json file

I am currently developing an application with a Spring Boot backend and an Angular frontend. To build the frontend, I am utilizing the frontend-maven-plugin in conjunction with Maven. However, when running "mvn spring-boot:run" command, an error is encount ...

Having trouble locating the Angular Material core theme within the asp.net core 2.0 template using Angular 5

CustomConfig.js const treeModules = [ '@angular/animations', '@angular/common', '@angular/compiler', '@angular/core', '@angular/forms', '@angular/http', '@angular ...

Explain to me the process of passing functions in TypeScript

class Testing { number = 0; t3: T3; constructor() { this.t3 = new T3(this.output); } output() { console.log(this.number); } } class T3 { constructor(private output: any) { } printOutput() { ...

Next js is throwing an error because it cannot accept objects as a React child. Instead, it found an error message stating "Response not successful: Received status code 401."

This app showcases Github issues by utilizing the graphql API. After finishing the app, I encountered an error without making any changes. The technologies used for this project include Next.js, Typescript, Material UI, Tailwind CSS, and GraphQL. https: ...

The combination of [(ngModel)] and name is not compatible with angular's ng-autocomplete feature, causing it to malfunction

I'm currently integrating ng-autocomplete with Angular 8, and encountering an issue. Here is the code snippet: HTML: <div class="field"> <label class="label">Nombre del condominio:</label> <div class="control"> ...

Angular Bootstrap causes misalignment of table column headings based on different properties in object

I have an object with two properties: person and vehicle. Both properties consist of arrays of data. I have separate column headings for the person and vehicle properties and display the data in tabular form. However, the column headings for both propertie ...

PhpStorm flawlessly detects ES7 type hinting errors

For my project, I have implemented TypeScript. While JavaScript's array includes() function has been valid since ECMA6, setting the lib parameter in tsconfig to "es6" results in a non-fatal error being thrown in the browser console when using the foll ...

Every time I attempt to submit the login form on the Ionic and Angular page, instead of capturing the values of the form group, the page simply refreshes

Struggling with submitting the login form in Ionic and Angular? When attempting to submit, the page reloads instead of capturing the form group values. I am utilizing angular reactive forms and form builder within the ionic framework. Need assistance in id ...

Enhance your property by adding the isDirty feature

Managing changes to properties of classes in TypeScript can be optimized by tracking only the fields that have actually changed. Instead of using an array to keep track of property changes, I am exploring the idea of implementing an isDirty check. By incor ...

In TypeScript, specifying that a type should only extend from an object does not effectively prevent strings from being accepted

My goal is to ensure proper typing for an attributes object that is stored in a wrapper class. This is necessary to maintain correct typing when accessing or setting individual attributes using the getOne/setOne methods as shown below. However, I am facin ...

The Typescript error "Attempting to call a function that does not have any callable signatures.(2349)"

Could you please assist me in resolving this issue: type IValidator = (value?: string) => string | undefined; type IComposeValidators = (validators: ((value?: string) => string | undefined)[]) => IValidator; export const composeValidators: ICompo ...

What is the best way to generate a unique UUID for every object created within a loop?

I am working on a typescript method that eliminates hashtags from a string and saves them in an array within a model. Each element in the hashtag array is assigned a unique UUID along with the complete string added to the model. However, I am facing an iss ...

Encountered error in Angular unit testing: Route matching failed to find a match

I am currently working on unit testing in my Angular 15 application. While running the test, I encountered the following error: Error: Cannot match any routes. URL Segment: 'signin' Below is the code for the unit test of my component: fdescribe ...