Troubleshooting the issue of setting the 'sort' property of undefined in an Angular material data table

I have been working on implementing the Angular material datatable, and I have successfully implemented the basic table and filter functionality.

However, when it comes to sorting, I encountered the following error:

Error:

ERROR TypeError: Cannot set property 'sort' of undefined
    at ListPostComponent.ngAfterViewInit (list-post.component.ts:53)
    at callHook (core.js:4708)
    at callHooks (core.js:4672)
    at executeInitAndCheckHooks (core.js:4612)
    at refreshView (core.js:11969)
    at refreshDynamicEmbeddedViews (core.js:13256)
    at refreshView (core.js:11916)
    at refreshComponent (core.js:13331)
    at refreshChildComponents (core.js:11622)
    at refreshView (core.js:11945)

Post model

import {User} from '../user/user.model';

export class Post {
    id: number;
    created_by: number;
    created_on: string;
    is_published: boolean;
    is_delete: boolean;
    title: string;
    slug: string;
    sub_title: string;
    content: string;
    tags: Array<string>;
    user: User
}

component.html

In the HTML, I have used the attributes matSort and mat-sort-header

<mat-form-field>
    <mat-label>Filter</mat-label>
    <input matInput (keyup)="applyFilter($event)" placeholder="Ex. ium">
</mat-form-field>
<div class="mat-elevation-z8">
    <table mat-table class="full-width-table" [dataSource]="dataSource" matSort aria-label="Elements">
        <!-- Id Column -->
        <ng-container matColumnDef="id">
            <th mat-header-cell *matHeaderCellDef mat-sort-header>Id</th>
            <td mat-cell *matCellDef="let row"><a [routerLink]="['/users/view', row.id]" class="a-style">{{row.id}}</a>
            </td>
        </ng-container>

        <!-- Title Column -->
        <ng-container matColumnDef="title">
            <th mat-header-cell *matHeaderCellDef mat-sort-header>Title</th>
            <td mat-cell *matCellDef="let row">{{row.title}}</td>
        </ng-container>

        <!-- Slug Column -->
        <ng-container matColumnDef="slug">
            <th mat-header-cell *matHeaderCellDef mat-sort-header>Slug</th>
            <td mat-cell *matCellDef="let row">{{row.slug}}</td>
        </ng-container>



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

component.ts

Here, I imported MatSort, MatTableDataSource and also imported MatSortModule in app.module.ts

import { Component, OnInit, ViewChild } from '@angular/core';
import {MatTableDataSource} from '@angular/material/table';
import {MatSort} from '@angular/material/sort';

import { PostService } from '../../service/post/post.service';
import { Post } from './../../models/post/post.model';

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

  @ViewChild(MatSort, {static: true}) sort: MatSort;
  displayedColumns = ['id', 'title', 'slug'];
  dataSource: MatTableDataSource<Post>;

  constructor(
    private postService: PostService
  ) {}

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

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

  getAllPosts() {
    this.postService.getAllPost().subscribe(
      (data) => {
        this.dataSource = new MatTableDataSource(data['posts']);        
      }
    )
  }

  applyFilter(event: Event) {
    const filterValue = (event.target as HTMLInputElement).value;
    this.dataSource.filter = filterValue.trim().toLowerCase();
  }
}

Can anyone guide me on where I might be going wrong?

Answer №1

The issue arises because the dataSource is not initialized when attempting to set the sort property value.

Solution 1: Update the following line:

dataSource: MatTableDataSource<Post>;

to:

dataSource = new MatTableDataSource<Post>();

Solution 2: Ensure that this.dataSource.sort is set immediately after defining the dataSource in getAllPosts method:

  getAllPosts() {
    this.postService.getAllPost().subscribe(
      (data) => {
        this.dataSource = new MatTableDataSource(data['posts']);
        this.dataSource.sort = this.sort;        
      }
    )
  }

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

The value could not be retrieved because the input name depends on the array index

To determine the name of the input based on the array index, use the following method: <div id="editAboutSantences<%=i%>" class="edit-container"> <div class="input-container"> <label> content: </label> ...

Updating webdriver-manager can sometimes result in a "spawn Unknown system error -86" message. This error

(Angular). webdriver-manager 12.1.7 is causing issues specifically on Intel-based Macs. When running e2e tests, the error message "spawn Unknown system error -86" is encountered. The bug has been addressed in webdriver-manager 12.1.8, however, I am facing ...

A guide on implementing gradient color fill for scatter plot points within Google Charts

I am interested in creating a scatter plot using a data set that includes three series: (1) for the x-axis, (2) for the y-axis, and (3) a third series that contains only 0 and 1 values. For this plot, I would like the points with a third series value of 0 ...

Using React's pure components in conjunction with hooks and state management

I am grappling with the best way to strategically implement components in React while maintaining a strong coding pattern. Typically, I am familiar with the concept of presentational and container components: presentational components solely display HTML ...

Tips for adding new elements to an array within an object

Here is a snippet of my current JSON data: { "_id" : 393, "item" : 34, "comments" : [ { "name" : "kevin", "messages" : [ "item", "item" ] }, { ...

Is there a way to accomplish this without using settimeout?

Whenever the Like button is pressed, I want to trigger the loading process I expect to see LOAD_POST_SUCCESS immediately after LIKE_POST_SUCCESS Pressing the Like button should initiate the load process After LIKE_POST_SUCESS, I want to see LOAD_POST_SU ...

Storing an array of objects in MySQL using Node.js

I am looking to insert an array of objects into a MySQL database using Node.js. I am familiar with inserting single data, editing, deleting, and other functions, but I am unsure how to accomplish this task. Below is the JSON format that I am utilizing for ...

Having trouble retrieving items from local storage in NextJS?

After logging in to my NextJS application, I store some user data in local storage. I'm attempting to create a small component that always shows the user's name. The problem I'm encountering is that sometimes it displays correctly and other ...

JavaScript For loop may not function consistently in IErowsers

Having spent two days searching, I've hit a roadblock and really need some help. I'm working with a javascript array that should give me the key to each subsequent array when iterated through. This is functioning as expected in most browsers, bu ...

Attempting to fetch a .ico file from the server side (Node ExpressJs) to the client side (ReactJS) triggers a 'TypeError: res.blob is not a function' error

My web application utilizes ReactJs on the front-end and NodeJs express on the back-end. I encountered an issue while attempting to retrieve and display a .ico file on the client-side using this code: Client side: async function getIcon() { try { ...

What is the best way to hide or show child elements within a tree structure using a toggle function

My HTML code needs to be updated to include a toggle span and JavaScript functionality. This will allow the child elements to be hidden and only displayed when the parent is clicked. I am a beginner with JavaScript and would appreciate any help in resolv ...

Which Angular tools should I be using: map, pipe, or tap?

When my component initializes, I retrieve data from the server import {Rules} from "../../interfaces/interfaces"; rules: Rules ngOnInit() { this.tt = this.rulesService.getUserClientRules().subscribe( t => { console.log(t) con ...

Layout display issue post redirection in React

I am facing an issue with my app that utilizes styled-components and material-ui. I have set up private routes based on user roles, and when a non-authenticated user is redirected to the login page, the layout fails to load properly. App.tsx import React ...

Efficiently adding multiple records to SQLite using Ionic 3

I'd like to optimize the bulk insertion process in Ionic 3. The current code I have works but it's quite slow. insertQuotation(value){ for(var i=0; i<=value.length; i++){ let data=[value[i].quotation_id,value[i].customer_name,value ...

transfer the variable from one module to another JavaScript file

I have developed a custom module and I am facing an issue where I need to pass the fetched database value $flag=1 to a JavaScript file in Drupal 7. However, when I try to access the variable 'aniv' in the JavaScript file, it shows as 'undefi ...

Utilizing the History API in conjunction with datatables

I am managing a dataTable object on a webpage that displays a list of releases and is accessible through the url /releases. I am looking to enhance its functionality by implementing the following features: If the url is /releases?query=<query>, the ...

Query executed but no results returned

Currently, I am practicing GQL and facing an issue when trying to display data in the Playground. I am attempting to access the jsonplaceholder API to fetch all posts and show them, but encountering the following error: Error: GRAPHQL_FORMAT_ERROR: Expec ...

ajaxStart - Display change inconsistency

These are some helpful comments to shorten and improve the readability of the code In my current project, I am using Javascript (Ajax) along with PHP (Laravel). I encountered an issue where I have set up two listeners in my ajax function. One listener is ...

divide various arrays into separate variables depending on their names

Exploring a more efficient approach - I have these arrays at my disposal: var model1 = ['10', '20', '30', '40','50','60']; var model2 = ['80', '100', '200', &a ...

How can I restrict website access to only specific IP addresses?

I am looking to restrict access to certain IP addresses on a website, but the issue is that dynamic IPs keep changing based on the source of internet connection. Is there a method to determine the static IP of the computer rather than relying on the dyna ...