dafna
dafna

Reputation: 973

Implement MatSort - Argument not assignable

I am confused to write the code for the Angular Material Mat-Sort-functionality. A get the following error dureing declaring my variable dataSource:

Argument of type 'Observable' is not assignable to parameter of type 'any[]'. Property length is missing in type 'Observable'.

Do you hava any ideas what I can try. Below you can find the code of my component.ts and the related service.ts

component.ts

import { Component, OnInit, ViewEncapsulation, ViewChild } from '@angular/core';
import { Location } from '@angular/common';
import { DataSource } from '@angular/cdk/collections';
import { Observable } from 'rxjs/Observable';

import { MatTableDataSource, MatSort } from '@angular/material';

import { Report } from './../../models/report';
import { RepGenService } from './../../services/rep-gen.service';

@Component({
    selector: 'app-rep-gen-report',
    templateUrl: './rep-gen-report.component.html',
    styleUrls: ['./rep-gen-report.component.css'],
    encapsulation: ViewEncapsulation.None
})
export class RepGenReportComponent implements OnInit {
    reports: Report[];

    dataSource = new MyDataSource(this.repGenService);
    //dataSource = new MatTableDataSource(this.repGenService.getReport()); // <--- error, not working
    displayedColumns = ['report_id', 'caption'];

    constructor(private repGenService: RepGenService, private location: Location) { }

    ngOnInit() {
        this.getRepGen_Report();
    }

    getRepGen_Report(): void {
        this.repGenService.getReport()
            .subscribe(reports => this.reports = reports);
    }

    save(reports: Report[]) {
        this.repGenService.setReport(this.reports);
    }

    goBack(): void {
        this.location.back();
    }

    //@ViewChild(MatSort) sort: MatSort;
    //ngAfterViewInit() {
    //    this.dataSource.sort = this.sort;  // therefor I need the imported MatTableDataSource
    //}
}

export class MyDataSource extends DataSource<any> {
    constructor(private repGenService: RepGenService) {
        super();
    }
    connect(): Observable<Report[]> {
        return this.repGenService.getReport();
    }
    disconnect() { }
}

service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';

import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map';

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

@Injectable()
export class RepGenService {

    constructor(public http: HttpClient) { }

    getReport(): Observable<any> {
        return this.http.get('/api/repGen_Report')
            .map(response => response);
    }

    setReport(reports) {
        this.http.post('/api/repGen_Report/update', reports
        ).subscribe();
    }
}

Thanks!

EDIT: I updated the component.ts

Upvotes: 1

Views: 6392

Answers (1)

Vinko Vorih
Vinko Vorih

Reputation: 2202

Problem is that your response is not loaded before call of getRepGen_Report().

You have to subscribe to get response in callback -> http.get is async method and you have to use promises or a little hack like this (set dataSource inside of curly brackets:

view: any[] = [];
    this.repGenService.get().subscribe(res => {
this.view = res;
this.dataSource = new TableDataSource(this.view);
})

after this you should declare class TableDataSource that extends DataSource and implement in constructor super and implement methods connect() and disconnect()

EDIT:

dataSource: MatTableDataSource;

ngOnInit() {
    this.repGenService.get().subscribe(res => {
      this.view = res;
      this.dataSource = new MatTableDataSource(this.view);
    });
  }

     export class MatTableDataSource extends DataSource<any>{
constructor(private view:any[]){
    super();
  }
  connect(): Observable<any[]>{
      return this.view;
  }
  disconnect(){}
}

Upvotes: 1

Related Questions