Problem on casting objects to array of a model in Angular - json

Here is my service code:
export class ProductListService {
constructor(private httpClient: HttpClient) {
}
getProducts(): Observable<IResponse> {
return this.httpClient.get<IResponse>('https://localhost:7127/Product/GetProductList');
}
}
and here is my component:
getProducts(): void {
this.productsService.getProducts()
.subscribe((response: IResponse) => {
this.products = <Product[]>response.data;
})
}
Which Product and IResponse are models:
export interface Product {
Id: string;
Title: string;
Description: string;
ImageUri: string;
CategoryId: string;
}
export interface IResponse {
data: object;
status: number;
}
When I get data from the api, it returns data as follow:
{
"data": [
{
"id": "e15",
"title": "LED TV 42 inch ",
"description": "-",
"imageUri": "C:\\wwwroot/cdn\\e15.jpg",
"categoryId": "tv"
},
{
"id": "e16",
"title": "LED TV 52 inch ",
"description": "-",
"imageUri": "C:\\wwwroot/cdn\\e16.jpg",
"categoryId": "tv"
}
],
"status": 200
}
I want to put the data into my products variable. How could I do this?

I agree with Sean Chase. Change the casing on your model. You also might want to cast the data property on the IResponse interface to Product[] (as a side note, interfaces don't start with I. That's a C# convention).
Are you using the products property in the template HTML? If so, you can use the pipe async syntax and replace the products property with an Observable<Product[]>. Here's an example
// models.ts
export interface Product {
id: string;
title: string;
description: string;
imageUri: string;
categoryId: string;
}
export interface IResponse {
data: Product[];
status: number;
}
// product-list.component.ts
import { Component, OnInit } from '#angular/core';
import { map, Observable, of, Subscription } from 'rxjs';
import { IResponse, Product } from './models';
import { ProductListService } from './products-list.service';
#Component({
selector: 'product-list',
template: `
<div *ngFor="let product of products$ | async">
<div>Id: {{ product.id }}</div>
<div>Title: {{ product.title }}</div>
<div>Description: {{ product.imageUri }}</div>
<div>CategoryId: {{ product.categoryId }}</div>
</div>
`
})
export class ProductListComponent implements OnInit {
products$: Observable<Product[]> = of([]);
constructor(private productsListService: ProductListService) {}
ngOnInit() {
this.products$ = this.productsListService.getProducts().pipe(map((res: IResponse) => res.data));
}
}
// product-list.service.ts
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Observable, of } from 'rxjs';
import { IResponse, Product } from './models';
#Injectable({
providedIn: 'root',
})
export class ProductListService {
// constructor(private httpClient: HttpClient) {}
getProducts(): Observable<IResponse> {
// return this.httpClient.get<IResponse>('https://localhost:7127/Product/GetProductList');
return of({
data: [
{
id: '1',
title: 'title-1',
description: 'description-1',
imageUri: '/images/image-1.jpg',
categoryId: '1'
} as Product,
{
id: '2',
title: 'title-2',
description: 'description-2',
imageUri: '/images/image-2.jpg',
categoryId: '2'
} as Product,
],
status: 200
});
}
}

Related

Why would an angular service api not render to data bindings in the html?

I am still new to angular... But, this html renders as a blank page, nothing is shown in the browser. Console.log will log out the data to the console so I know it is visible. This also causes blank rows in a p-table or any other table that you might be using.
What am I doing wrong?
component.html
<div *ngFor="let item of myData">{{ item.id }}</div> <!-- should be: 1 2 3 -->
<div>{{ item[0].id }}</div> <!-- should be: 1 -->
component.ts
#Component({
selector: 'app-testing-table',
templateUrl: './testing-table.component.html',
styleUrls: ['./testing-table.component.css'],
})
export class TestingTableComponent implements OnInit {
myData: Posts[] = [];
constructor(
private postService: PostService,
) {}
ngOnInit(): void {
this.postService.get().subscribe((resp) => {
console.log('got all posts', resp);
this.myData = resp;
});
}
}
service.ts
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/internal/Observable';
import { Posts } from '../models/posts';
#Injectable({
providedIn: 'root',
})
export class PostService {
public URL = 'https://something.com/typicode/demo/posts';
constructor(protected http: HttpClient) {}
public get(): Observable<Array<Posts>> {
return this.http.get<Array<Posts>>(`${this.URL}`);
}
}
model.ts
export class Posts {
id: number;
title: string;
}
Response Data from the API get() service.ts
[
{
"ID": 1,
"Title": "Post 1"
},
{
"ID": 2,
"Title": "Post 2"
},
{
"ID": 3,
"Title": "Post 3"
}
]
This took me a few good days of work with some help from a friend to find out angular is very strict with how it maps the JSON to the Model. The response data has to match 1:1 with the case or it wont work. The error is here:
Make the models match the response:
model.ts
export class Posts {
ID: number;
Title: string;
}
OR
Have the api service change what it returns as JSON, and have it return this instead:
Response Data from the API get() service.ts
[
{
"id": 1,
"title": "Post 1"
},
{
"id": 2,
"title": "Post 2"
},
{
"id": 3,
"title": "Post 3"
}
]

Angular 6 - Get current route and its data

How to get the current route you're in and its data, children and parent?
If this is the route structure:
const routes: Routes = [
{path: 'home', component: HomeComponent, data: {title: 'Home'}},
{
path: 'about',
component: AboutComponent,
data: {title: 'About'},
children: [
{
path: 'company',
component: 'CompanyComponent',
data: {title: 'Company'}
},
{
path: 'mission',
component: 'MissionComponent',
data: {title: 'Mission'}
},
...
]
},
...
]
If I am currently in CompanyComponent, how do I get my current route w/c is Company, get its parent w/c is about, its data and its siblings such as mission, etc.?
#Component({...})
export class CompanyComponent implements OnInit {
constructor(
private router: Router,
private route: ActivatedRoute
) {}
ngOnInit() {
// Parent: about
this.route.parent.url.subscribe(url => console.log(url[0].path));
// Current Path: company
this.route.url.subscribe(url => console.log(url[0].path));
// Data: { title: 'Company' }
this.route.data.subscribe(data => console.log(data));
// Siblings
console.log(this.router.config);
}
}
constructor(
private router: Router,
private route: ActivatedRoute,
) {
}
ngOnInit() {
this.router.events.pipe(
filter(event => event instanceof NavigationEnd),
map(() => {
return this.getHeaderClasses();
}),
)
.subscribe((headerClasses: string | null) => {
this.headerClasses = headerClasses;
});
this.headerClasses = this.getHeaderClasses();
}
getHeaderClasses(): string | null {
let child = this.route.firstChild;
while (child) {
if (child.firstChild) {
child = child.firstChild;
} else if (child.snapshot.data && child.snapshot.data['headerClasses']) {
return child.snapshot.data['headerClasses'];
} else {
return null;
}
}
return null;
}
routing
{
path: 'list',
component: DialogListComponent,
data: {
headerClasses: 'col-lg-8',
},
},
You can access the route's data property from the snapshot like this:
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
#Component({
templateUrl: './app/home/welcome.component.html'
})
export class WelcomeComponent implements OnInit {
public pageTitle: string;
constructor( private route: ActivatedRoute) {
}
ngOnInit(): void {
this.pageTitle = this.route.snapshot.data['title'];
}
}
#Component({...})
#UntilDestroy()
export class CompanyComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit() {
this.router.events
.pipe(
untilDestroyed(this),
filter((event): event is NavigationEnd => event instanceof NavigationEnd),
map((event: NavigationEnd) => event.url)
)
.subscribe(url=> {
console.log(url);
});
}
}

How to get the same value in a Json/array as the user input?

I want to search through a Json and get the same value as the user input.
I don't know why my code is not working. So e.g. the user search for car. If car is in the Json. It should show in the page the word car.
Here is my code:
Pipe:
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'filter'
})
export class FilterPipe implements PipeTransform {
transform(items: any[], searchText: string): any[] {
if(!items) return [];
if(!searchText) return items;
searchText = searchText.toLowerCase();
return items.filter( it => {
return it.toString().toLowerCase().includes(searchText);
});
}
}
Html:
<li *ngFor="let char of characters | filter : searchText" >
{{ searchText}}
{{char.name}}
{{char.age}}
</li>
</ul>
Component:
export class SearchComponent {
characters: any[] = [
{
"name": "audi",
"age": 1999
},
{
"name": "toyota",
"age": 2000
}
}
your pipe should be like this
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'filter'
})
export class FilterPipe implements PipeTransform {
transform(items: any[], searchText: string): any[] {
if(!items) return [];
if(!searchText) return items;
searchText = searchText.toLowerCase();
return items.filter( it => {
return it.name.toString().toLowerCase().includes(searchText);
});
I think it.toString() returns something like: [object Object]
Try JSON.stringify(it).toLowerCase().includes(searchText);

How to pass data received from service to angular datatable

I have just started working on Angular 4 and I am trying to render some data which I receive from angular service in json format, into angular-datatable, but whichever option i try its not working for me.
The table is coming, the columns are coming, however the data inside the columns are not displaying.
Any help would be great,
Thanks in advance..!!!!
Please find my code below:
component.html
<table datatable [dtOptions]="dtOptions" class="row-border hover"></table>
component.ts
import { Component, OnInit } from '#angular/core';
import { FleetDataService } from '../../services/fleet-data.service';
import { Subject } from 'rxjs/Subject';
#Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit {
private fleetData: any;
dtOptions: DataTables.Settings = {};
dtTrigger: Subject<any> = new Subject();
constructor(private getFleetData:FleetDataService) { }
ngOnInit() {
this.getFleetData.getFleetData().subscribe(
fleetData => {
this.fleetData = fleetData;
console.log(this.fleetData);
this.dtTrigger.next();
},
err => {
console.log(err);
}
);
this.dtOptions = {
pagingType: 'full_numbers',
columns: [{
title: 'First Name',
data: this.fleetData
}, {
title: 'Last Name',
data: this.fleetData
}, {
title: 'Score',
data: this.fleetData
}]
};
}
}
component.service
import { Injectable } from '#angular/core';
import { HttpModule, Http, Response, Headers, RequestOptions } from
'#angular/http';
import { Observable } from 'rxjs/Rx';
#Injectable()
export class FleetDataService {
constructor(private http: Http) { }
getFleetData() {
return this.http.get("../../assets/data/test.json")
.map((res:Response) => res.json())
.catch((error:any) => Observable.throw(error.json().error || 'Server
Error'));
}
}
test.json
[{
"FirstName": "Jill",
"LastName": "Smith",
"Score": "disqualified"
}, {
"FirstName": "Eve",
"LastName": "Jackson",
"Score": "94"
}, {
"FirstName": "John",
"LastName": "Doe",
"Score": "80"
}, {
"FirstName": "Adam",
"LastName": "Johnson",
"Score": "67"
}]
You set your dtOptions outside the subscribe.
If you do this the fleetData stays empty so dtOptions is never set correctly, because an Observable is asynchronous. I propose this code:
export class DashboardComponent implements OnInit {
dtOptions: DataTables.Settings = {};
dtTrigger: Subject<any> = new Subject();
constructor(private getFleetData:FleetDataService) { }
ngOnInit() {
this.getFleetData.getFleetData().subscribe(
fleetData => {
console.log(fleetData);
this.buildDtOptions(fleetData)
this.dtTrigger.next();
},
err => {
console.log(err);
});
}
private buildDtOptions(fleetData: any): void {
this.dtOptions = {
pagingType: 'full_numbers',
columns: [
{title: 'First Name', data: fleetData},
{title: 'Last Name', data: fleetData},
{title: 'Score', data: fleetData}
]
};
}
}
For this error: ERROR TypeError: Cannot read property 'aDataSort' of undefined. You can do a spinner (ngIf / else) in the view and when data are loaded you display the datatable

Supplied parameters do not match any signature of call target on api call angular4

I am consuming an api to Covalent UI, on user service. Which needs to post some data from an endpoint to the table as illustrated on the example from the GitHub.
Here is the modification I have made to the service.
import { Provider, SkipSelf, Optional, InjectionToken } from '#angular/core';
import { Response, Http } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { HttpInterceptorService, RESTService } from '#covalent/http';
import { ApiService } from '../../../../services/api.service';
import { AuthService } from '../../../../services/auth.service';
export interface IUser {
_id: string;
email:string;
createdAt: Date;
profile: {
name: string;
gender: string;
location: String;
picture: {
// data: Buffer;
contentType: string;
}
}
}
export class UserService extends RESTService<IUser> {
constructor(private _http: HttpInterceptorService, api: string,
private authService: AuthService,
private api2: ApiService,) {
super(_http, {
baseUrl: api,
path: '/dashboard/users',
});
}
staticQuery(): Observable<IUser[]> {
// return this._http.get('data/users.json')
// .map((res: Response) => {
// return res.json();
// });
return this.api2.get('auth/account/users')
.map((res: Response) => {
return res.json();
});
}
}
export const USERS_API: InjectionToken<string> = new InjectionToken<string>('USERS_API');
export function USER_PROVIDER_FACTORY(
parent: UserService, interceptorHttp: HttpInterceptorService, api: string): UserService {
return parent || new UserService(interceptorHttp, api);//<---- This is where I get the error mention.
}
export const USER_PROVIDER: Provider = {
// If there is already a service available, use that. Otherwise, provide a new one.
provide: UserService,
deps: [[new Optional(), new SkipSelf(), UserService], HttpInterceptorService, USERS_API],
useFactory: USER_PROVIDER_FACTORY,
};
JSON api data
[
{
"_id": "59d665c3acbde702b47d3987",
"updatedAt": "2017-10-07T17:23:00.498Z",
"createdAt": "2017-10-05T17:02:59.526Z",
"email": "me#mail.com",
"password": "$2a$05$z1mRUWqqUfM8wKMU/y9/sOLssAKcV7ydxi0XJyTR1d3BI2X7SSsoy",
"tokens": [],
"role": "admin",
"__v": 0,
"profile": {
"name": "F.name L.name",
"gender": "Female",
"location": "my place",
"avatar": {
"contentType": "image/png",
"data": "iVBORw0KGgoAAAANSUhEUgAAAaYAAAFmCAYAAAAmm....."
}
}
}
]
Am not sure what am doing wrong, I will appreciate your comment for this fix.
I get the error bellow.
users/services/user.service.ts (51,20): Supplied parameters do not match any signature of call target.
From this line of code
As #Philipp mentioned in the comments.
The class UserService expects 4 arguments in the constructor, but you are only providing 2 in the USER_PROVIDER_FACTORY function.
Therefore your factory should be defined:
export function USER_PROVIDER_FACTORY(
parent: UserService, interceptorHttp: HttpInterceptorService, api: string,
authService: AuthService, api2: ApiService
): UserService {
return parent || new UserService(interceptorHttp, api, authService, api2)
}