Reputation: 97467
I'm trying to adapt the material examples like the following:
import { Component } from '@angular/core';
import { MatTableDataSource } from '@angular/material';
import { User } from '../models/user.model';
import { XService } from './x.service';
@Component({
selector: 'x-component',
styleUrls: ['x.component.css'],
templateUrl: 'x.component.html',
})
export class XComponent {
constructor(private xService: XService) {
}
displayedColumns = ['c1', 'c2', 'c3', 'c4'];
dataSource = new MatTableDataSource<User>(this.xService.getUsers());
applyFilter(filterValue: string) {
filterValue = filterValue.trim(); // Remove whitespace
filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
this.dataSource.filter = filterValue;
}
}
The getUsers() looks like this:
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { User } from '../models/user.model';
@Injectable()
export class XService {
constructor(private http:HttpClient) {}
private userUrl = 'http://localhost:8080/X';
public getUsers() {
return this.http.get<User[]>(this.userUrl);
}
}
The user model looks like this:
export class User {
c1 : string;
c2 : string;
c3 : string;
c4 : string;
}
The above REST API localhost:8080/X
will result in something like this:
[ {
"c1" : 1,
"c2" : "I",
"c3" : 244.0,
"c4" : 0.0,
}, {
...
}
]
but unfortunately if I try to build it via:
ng build
I get the following:
Your global Angular CLI version (1.7.1) is greater than your local
version (1.6.3). The local Angular CLI version is used.
To disable this warning use "ng set --global warnings.versionMismatch=false".
Date: 2018-02-26T11:03:55.196Z
Hash: 7f10a43625c2473d5bc9
Time: 4417ms
chunk {inline} inline.bundle.js, inline.bundle.js.map (inline) 5.83 kB [entry] [rendered]
chunk {main} main.bundle.js, main.bundle.js.map (main) 303 bytes [initial] [rendered]
chunk {polyfills} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 323 bytes [initial] [rendered]
chunk {scripts} scripts.bundle.js, scripts.bundle.js.map (scripts) 69.8 kB [initial] [rendered]
chunk {styles} styles.bundle.js, styles.bundle.js.map (styles) 163 kB [initial] [rendered]
ERROR in src/app/x/x.component.ts(21,45): error TS2345:
Argument of type 'Observable<User[]>' is not assignable
to parameter of type 'User[]'.
Property 'includes' is missing in type 'Observable<User[]>'.
Based on the examples I would say it should be working but obviously it does not. The question is: Can someone give a hint/tip where to search or what the problem might be?
Update:
After changing the getUsers() into this (By suggestion of axl-code)
public getUsers() {
return this.http.get<User[]>(this.userUrl).subscribe((data: any) => {
return data;
});
}
I got the following error message during ng build
:
ERROR in src/app/x/x.component.ts(21,45): error TS2345:
Argument of type 'Subscription' is not assignable to
parameter of type 'User[]'.
Property 'includes' is missing in type 'Subscription'.
Upvotes: 6
Views: 19184
Reputation: 97467
So after more diving into the problem I found the following solutions:
First the method getUsers in the service looks like this:
public getUsers() : Observable<User[]> {
return this.http.get(this.userUrl).map(response => {
const users = response.json();
return users.map((user) => new User(user));
});
}
The use model class has been enhanced like this:
constructor(values: Object = {}) {
Object.assign(this, values);
}
The component X now looks like this:
export class XComponent implements OnInit {
users: User[] = []
constructor(private xService: XService) {
}
displayedColumns = ['c1', 'c2', 'c3', 'c4'];
dataSource = new MatTableDataSource(this.users);
applyFilter(filterValue: string) {
filterValue = filterValue.trim(); // Remove whitespace
filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
this.dataSource.filter = filterValue;
}
public ngOnInit() {
this.xService.getUsers()
.subscribe(
(users) => {
this.users = users;
}
);
}
}
By using the above I get it compiled without any error.
Upvotes: 0
Reputation: 3418
Based on your provided code, try it this way
export class XComponent {
dataSource = new MatTableDataSource<User[]>(); // note that you are just instantiating a
//MatTableDataSource here. There's no data yet. Add it in the constructor
// Note that in your original code, you are doing this <User> instead of <User[]>
constructor(private xService: XService) {
this.xService.getUsers().subscribe ( users => {
this.dataSource.data = users;
})
}
displayedColumns = ['c1', 'c2', 'c3', 'c4'];
applyFilter(filterValue: string) {
filterValue = filterValue.trim(); // Remove whitespace
filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
this.dataSource.filter = filterValue;
}
}
You don't need to change anything in your getUsers()
. Returning it as Observable<Users[]>
should work because you are subscribing to it in your XComponent, thus you can get just the "Users[]".
Upvotes: 3
Reputation: 57981
the "dataSource" of a MatTable can be a Observable or an Array. I don't know about Material, but, reading the documentation, I supouse you can write
dataSource:MatTableDataSource<User>=this.xService.getUsers();
Upvotes: 0
Reputation: 38683
After your update in your question. please use map
instead of subscribe
public getUsers() {
return this.http.get<User[]>(this.userUrl)
.map((data: any) => {
data;
})
.catch(error => {
return Observable.throw(error);
});;
}
import this in your service import { Observable } from 'rxjs/Observable';
Your component should be
this.xService.getUsers().subscribe(response => {
// do what you want from the response.
});
Upvotes: 0
Reputation: 2274
This code is returning an Observable:
public getUsers() {
return this.http.get<User[]>(this.userUrl);
}
and here:
dataSource = new MatTableDataSource<User>(this.xService.getUsers());
you are injecting it. If you want to return the content of the observable try:
public getUsers() {
return this.http.get<User[]>(this.userUrl).subscribe((data: any) => {
return data;
});
}
Upvotes: 1