Seeker
Seeker

Reputation: 209

data from websockets to Angular mat table

I have been writing a code to get data from my server via websockets and display it in Angular mat-table. I am having issues as the table data is not refreshing. I am able to display the data in a simple table. But the same is not getting displayed in a mat-table. In one of the blogs, i read to use _updateChangeSubscription / _renderChangesSubscription but nothing works. I even tried using @ViewChild component to trigger the data refresh. Even that is not working. below are my app.compnent.html and app.component.ts for reference

app.component.html

 <!-- Simple table where data is getting displayed-->
    <div>
      <table border="10">
        <thead>
          <tr>
            <th> Id</th>
            <th> Name</th>
            <th> Output </th>
          </tr>
        </thead>
        <tbody>
          <tr *ngFor="let data of result">
            <th>{{ data.id }}</th>
            <td>{{ data.name }}</td>
            <td>{{ data.output }}</td>
          </tr>
        </tbody>
      </table>
    </div>

<!-- mat-table where data is not getting displayed -->

    <mat-table [dataSource]="datasource">
    <ng-container matColumnDef="id">
      <mat-header-cell *matHeaderCellDef> id. </mat-header-cell>
      <mat-cell *matCellDef="let element"> {{ element.id }}  </mat-cell>
    </ng-container>

    <ng-container matColumnDef="name">
      <mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
      <mat-cell *matCellDef="let element">  {{ element.name }}  </mat-cell>
    </ng-container>


    <ng-container matColumnDef="output">
      <mat-header-cell *matHeaderCellDef> Output </mat-header-cell>
      <mat-cell *matCellDef="let element">  {{ element.output }}  </mat-cell>
    </ng-container>

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

app.component.ts

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.styl']
})
export class AppComponent {
  title = 'web socket example';
  private serverUrl = 'http://localhost:8080/server'
  private stompClient;
  @ViewChild(MatTable) table : MatTable<any>;


  result = [];
  displayedColumns: string[] = ['id', 'name', 'output'];
  datasource : MatTableDataSource<Element[]>;



  constructor(){
    this.initializeWebSocketConnection();
  }


 stompSucessCallBack = () =>  {

   this.stompClient.subscribe("/messages", (message) => {
    if(message.body) {      

    this.result.push(JSON.parse(message.body)); 
    this.datasource.data.push(message.body); 
    this.datasource._updateChangeSubscription;

    this.datasource._renderChangesSubscription;
    this.table.renderRows;
    console.log("******");
    console.trace(this.datasource.data);

  }
});
 }


  initializeWebSocketConnection(){
    let ws = new SockJS(this.serverUrl);
    this.stompClient = Stomp.over(ws);

    this.datasource = new MatTableDataSource();
    let that = this;
    this.stompClient.connect({}, that.stompSucessCallBack);
  }

}

packge.json

"dependencies": {
    "-": "0.0.1",
    "@angular/animations": "~9.1.7",
    "@angular/cdk": "^9.2.4",
    "@angular/common": "~9.1.7",
    "@angular/compiler": "~9.1.7",
    "@angular/core": "~9.1.7",
    "@angular/forms": "~9.1.7",
    "@angular/material": "^9.2.4",
    "@angular/platform-browser": "~9.1.7",
    "@angular/platform-browser-dynamic": "~9.1.7",
    "@angular/router": "~9.1.7",
    "jquery": "^3.5.1",
    "net": "^1.0.2",
    "rxjs": "~6.5.4",
    "sockjs-client": "^1.4.0",
    "stompjs": "^2.3.3",
    "tslib": "^1.10.0",
    "zone.js": "~0.10.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.901.6",
    "@angular/cli": "~9.1.6",
    "@angular/compiler-cli": "~9.1.7",
    "@types/node": "^12.11.1",
    "@types/jasmine": "~3.5.0",
    "@types/jasminewd2": "~2.0.3",
    "codelyzer": "^5.1.2",
    "jasmine-core": "~3.5.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~5.0.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~2.1.0",
    "karma-jasmine": "~3.0.1",
    "karma-jasmine-html-reporter": "^1.4.2",
    "protractor": "~5.4.3",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~3.8.3"
  }

Upvotes: 1

Views: 1408

Answers (1)

Sam Fessler
Sam Fessler

Reputation: 66

I ran across a similar problem recently.. There are a couple differences between your solution and my working one.

First- Your data source initialization:

this.datasource = new MatTableDataSource<Element>([]);

And in your callback:

let result = <Element>JSON.parse(message.body);
const datasource = this.datasource.data;
datasource.push(result);
this.datasource.data = datasource;

Component:

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.styl']
})
export class AppComponent {
  title = 'web socket example';
  private serverUrl = 'http://localhost:8080/server'
  private stompClient;

  displayedColumns: string[] = ['id', 'name', 'output'];
  datasource : MatTableDataSource<Element>;


  constructor(){
    this.initializeWebSocketConnection();
  }


 stompSucessCallBack = () =>  {

   this.stompClient.subscribe("/messages", (message) => {
    if(message.body) {
  
    let result = <Element>JSON.parse(message.body);
    const datasource = this.datasource.data;
    datasource.push(result);
    this.datasource.data = datasource;

  }
});
 }


  initializeWebSocketConnection(){
    let ws = new SockJS(this.serverUrl);
    this.stompClient = Stomp.over(ws);

    this.datasource = new MatTableDataSource<Element>([]);
    let that = this;
    this.stompClient.connect({}, that.stompSucessCallBack);
  }

}

If this still fails, it could be a mapping error... I have a model for my JSON to parse to. I suggest you do something similar.

It could also be a rendering issue, not likely to be the problem, but just a small html difference between our two solutions:

Try replacing mat-header-cell with th:

<th  mat-header-cell *matHeaderCellDef>

And mat-cell with td:

<td mat-cell *matCellDef="let element">

Upvotes: 2

Related Questions