How to pass data received from service to angular datatable - json

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

Related

Unit Testing Angular component with service : Cannot read property 'diagonisticData' of undefi

I am new to angular testing. I have a component, nested json and a service. The app works fine but during testing values are not being populated into the component. Please help.I have attached the service, json object,component and spec file.
I am not sure if I am following the right approach in spec file.
App component -Hub-Details-component.ts
export class HubDetailsComponent implements OnInit {
ngOnInit(): void {}
public jsonData:any = []
public diagnosticsData:any = [];
public dummy:any = [];
public hubData:any;
constructor(private dataService: DataService) {}
handleData()
{
this.dataService.getData()
.subscribe(response =>{
if(response!=null)
{
this.jsonData=response;
console.log(this.jsonData);
this.dummy=this.jsonData.result;
console.log(this.dummy);
this.diagnosticsData=this.dummy.diagnosticData;
const DataArray = [];
for(const element in this.diagnosticsData)
{
DataArray.push({
id:element,
name:this.diagnosticsData[element]
});
}
console.log(DataArray);
this.hubData=DataArray;
}
});
}
}
DataService
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'})
export class DataService {
public url = '/assets/Data/Data.json'
constructor(private http: HttpClient ) { }
getData = () => {
const url = 'assets/Data/Data.json';
return this.http.get(url);
}}
json file
{
"result"
{
"abc"
{
"name" :"abc",
"tag" : "xyz",
"status": "qwe"
}
}
}
spec.ts
it('should get data from dataservice',fakeAsync(()=>{
const fixture =
TestBed.createComponent(HubDetailsComponent);
const component =
fixture.debugElement.componentInstance;
const service =
fixture.debugElement.injector.get(DataService);
let spy_getPosts =
spyOn(service,'getData').and.callFake(() => {
return of([{"result"{
"abc"
{
"name" :"abc",
"tag" : "xyz",
"status": "qwe"
}
}
}]).pipe(delay(2000));});
fixture.detectChanges();
component.handleData();
tick(2000);
expect(component.jsonData).toEqual([{
{"result"{
"abc"
{
"name" :"abc",
"tag" : "xyz",
"status": "qwe"
}
}
}
}]);
}));
Thanks in advance.
Try this:
// In your spec file, mock the service;
#Injectable()
class MockDataService extends DataService {
getData() {
const mockData = {
result: {
diagnosticData: [
{ mock1: 'value1' },
{ mock2: 'value2' }
]
}
}
return of(mockData);
}
}
describe('Your Component Name you are testing', () => {
let dataService;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [],
imports: [...yourImports],
schemas: [NO_ERRORS_SCHEMA],
providers: [
{
provide: DataService,
useClass: MockDataService
}
]
}).compileComponents();
dataService = TestBed.get(DataService);
}));
// Now your test case:
it('should call #handleData() method', () => {
spyOn(component, 'handleData').and.callThrough();
component.handleData();
expect(component.handleData).toHaveBeenCalled();
});
// Thats it. You do not need to do anything else;
})

Pushing json file into a localStorage array

I have a task to make CRUD app in angular 8 but I have to push somehow my JSON file into local storage and then be able to add new objects. I made an array of contacts and put some data in there and if someone can help me to put this JSON data in that array of objects, so I can read all my contacts from localStorage.
I have tried to subscribe to contacts and it kinda works but won't add data to a localStorage.
Contacts Service
import { Contact } from '../models/contact';
import { IContact } from '../models/contact';
import { Observable } from 'rxjs/Observable';
import { HttpClient } from '#angular/common/http';
import { Injectable, OnInit } from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class ContactService {
contacts: Array < Contact > = [{
first_name: "Darko",
last_name: "Lesevic",
emails: ["darko1#test.com", "darko2#test.com"],
phones: [123456789, 123456789, 123456789],
photo: ''
}];
constructor(private http: HttpClient) {
//this won't work
// this.getJSON().subscribe(data => {
// this.contacts = data;
// console.log(data);
// });
}
getJSON(): Observable < Contact[] > {
return this.http.get < Contact[] > ("/assets/data/contacts.json");
}
contacts_serialized: any;
contacts_deserialized: any;
localStorageObj() {
this.contacts_serialized = JSON.stringify(this.contacts); //converts data to string
localStorage.setItem('id', this.contacts_serialized);
this.contacts_deserialized = JSON.parse(localStorage.getItem('id')); //converts string to data
console.log(this.contacts_deserialized);
}
}
Calling contact Service here
import { ContactService } from '../services/contact.service';
import { Component, OnInit } from '#angular/core';
import { Observable } from 'rxjs';
import { Contact } from '../models/contact';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
constructor(private contactService: ContactService) { }
ngOnInit() {
this.contactService.localStorageObj();
}
}
MY JSON FILE
[{
"first_name": "Afonso",
"last_name": "Pinto",
"emails": ["mail01#gmail.com", "mail02#gmail.com"],
"phones": ["123-234-566", "123-234-567", "123-234-568"],
"photo": "http://lorempixel.com/400/300/people/"
},
{
"first_name": "Alexandre",
"last_name": "Paiva",
"emails": ["mail01#gmail.com"],
"phones": ["123-234-560", "123-234-561"],
"photo": null
},
{
"first_name": "Oea",
"last_name": "Romana",
"emails": ["mail01#gmail.com", "mail02#gmail.com"],
"phones": ["123-234-566", "123-234-567", "123-234-568"],
"photo": "http://lorempixel.com/400/300/people/"
},
{
"first_name": "Nuria",
"last_name": "Pelayo",
"emails": ["mail01#gmail.com", "mail02#gmail.com"],
"phones": ["123-234-568"],
"photo": "http://lorempixel.com/400/300/people/"
},
{
"first_name": "Lisandro",
"last_name": "Matos",
"emails": ["mail01#gmail.com", "mail02#gmail.com"],
"phones": ["123-234-566", "123-234-567"],
"photo": null
}
]
First of all, you need to subscribe and then use setItem
this.contactService.getJSON().subscribe((data) => {
localStorage.setItem('myData', JSON.stringify(data);
});

Call JSON with subscribe or promise

If I use the promise function, I get the Error:
**Property 'TEST' does not exist on type 'Object'**
my ServiceClass
with the method:
getTEST() {
return this.http.get(this.configUrl)
.toPromise()
.then(res => <Tariftabelle[]> res.TEST)
.then(data => { return data; });
}
And my json-Date:
{
"TEST": [
{"leistung": "hello", "sb": "World"},
{"leistung": "hellooo", "sb": "Test-Wordl"}
],
"TEST2": [
{"leistung": "hola", "basic": "1", "premium": "2", "exzellent": "3"},
{"leistung": "hola two", "basic": "2", "premium": "4", "exzellent": "6"},
{"leistung": "hola three", "basic": "4", "premium": "7", "exzellent": "9"}
]
}
or how can iIuse subscribe without promise?
Service
#Injectable({
providedIn: 'root'
})
export class MyService {
getTEST(): Observable<any> {
return this.http.get(this.configUrl);
}
}
Component
#Component({
selector: 'app-my-component',
templateUrl: './my-component.html',
styleUrls: ['./my-component.scss']
})
export class MyComponent implements OnInit {
data: any;
constructor(private myServ: MyService) {}
ngOnInit() {
this.myServ.getTEST().subscribe(res => {
this.data = res;
});
}
}
Template
<pre>{{ data | json }}</pre>
As you can see in the init of your component you subscribe for the service getTEST request. In the subscribe, when you receive json data, you assign them to your local data variable. Now you can access it into your template.

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)
}

JSON data with angular2-highcharts

I want to create chart based on the JSON data.
I using angular2-highcharts my ChartsMain component looks like:
#Component({
moduleId: module.id,
selector: 'charts',
templateUrl: 'charts.html',
directives: [CHART_DIRECTIVES,]
providers: [DataService]
})
export class ChartsMain {
result: Data[];
constructor(DataService:DataService) {
DataService.getData().subscribe(res => this.result = res);
this.options = {
chart: {
type: "candlestick"
},
title: {
text: "JSON data"
},
xAxis: {
type: "category",
allowDecimals: false,
title: {
text: ""
}
},
yAxis: {
title: {
text: "Number"
}
},
series: [{
name: "Hour",
data: this.result
}]
};
}
options: Object;
And my DataService looks:
#Injectable()
export class DataService {
http: Http;
constructor(http: Http) {
this.http = http;
}
getData(): Observable<Array<Data>> {
return this.http.get('http://JSON-DATA')
.map(this.extractData)
.catch(this.handleError)
}
private extractData(res: Response) {
let body = res.json();
return body || { };
}
private handleError(error: any) {
// In a real world app, we might use a remote logging infrastructure
// We'd also dig deeper into the error to get a better message
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg); // log to console instead
return Observable.throw(errMsg);
}
}
My chart
Where is a problem, why is chart empty? How do I fill the chart with JSON data. JSON data must be in any specific format?
A candlestick chart is typically used to present the open, high, low and close price over a period of time..
Sample expected JSON format looks like this-
[
[1250553600000,23.09,23.46,23.06,23.43],
[1250640000000,23.25,23.61,23.21,23.51],
[1250726400000,23.57,23.82,23.52,23.76],
[1250812800000,23.95,24.20,23.83,24.17],
[1251072000000,24.30,24.39,24.04,24.15],
[1251158400000,24.21,24.42,24.16,24.20],
[1251244800000,24.13,24.22,23.82,23.92],
[1251331200000,24.11,24.22,23.55,24.21],
[1251417600000,24.61,24.64,24.08,24.29],
[1251676800000,24.02,24.12,23.79,24.03],
]
Here is sample component with candlestick highchart-
import { Component } from '#angular/core';
import {JSONP_PROVIDERS, Jsonp} from '#angular/http';
import { CHART_DIRECTIVES } from 'angular2-highcharts';
#Component({
selector: 'high-chart',
directives: [CHART_DIRECTIVES],
providers: [JSONP_PROVIDERS],
template: `
<h2> This is HighChart CandleStick component </h2>
<chart type="StockChart" [options]="options3"></chart>
`
})
export class HighChartsComponent {
options3: Object;
constructor(jsonp : Jsonp) {
jsonp.request('https://www.highcharts.com/samples/data/jsonp.php?a=e&filename=aapl-ohlc.json&callback=JSONP_CALLBACK').subscribe(res => {
this.options3 = {
title : { text : 'CandleSticks' },
rangeSelector : {
selected : 1
},
series : [{
type : 'candlestick',
name : 'CandleSticks',
data : res.json(),
dataGrouping : {
units : [
[
'week', // unit name
[1] // allowed multiples
], [
'month',
[1, 2, 3, 4, 6]
]
]
},
tooltip: {
valueDecimals: 2
}
}]
};
});
}
EDIT:
In your case you are not setting chart options inside subscribe. You should set like this-
this._http.get('http://knowstack.com/webtech/charts_demo/data.json')
.map(this.extractData)
.subscribe((response) => {
this.options = {
title : { text : 'knowstack' },
series : [{
name : 'knowstack',
data : response.json()
}]
};
},
(error) => {
this.errorMessage = <any>error
});
Please note - data from knowstack will only work with simple charts (not candlestick)
EDIT 2: column chart
Please refer below configuration. This is how you can use column chart.
this.options1 = {
title : { text : 'simple column chart' },
series: [{
type : 'column',
data: [["Maths",15],["Physics",16],["Biology",18],["Chemistry",19]]
}]
};
EDIT 3: sample of key-value pair json
import { Component } from '#angular/core';
import { CHART_DIRECTIVES } from 'angular2-highcharts';
#Component({
selector: 'my-app',
directives: [CHART_DIRECTIVES],
styles: [`
chart {
display: block;
}
`]
template: `<chart [options]="options"></chart>`
})
class AppComponent {
constructor() {
var data = [{"key":"Math","value":98},{"key":"Physics","value":78},{"key":"Biology","value":70},{"key":"Chemistry","value":90},{"key":"Literature","value":79}];
this.options = {
title : { text : 'simple chart' },
xAxis: {
type: 'category'
},
series: [{
data: data.map(function (point) {
return [point.key, point.value];
})
}]
};
}
options: Object;
}
Ok it is work. I use service which in my first post, I just changed component: constructor(http: Http, jsonp : Jsonp, DataService:DataService) {
DataService.getData().subscribe(res => this.result = res);
http.request('').subscribe(res => {
this.options = {
chart: {
type: 'column'
},
plotOptions: {
column: {
zones: [{
value: 12,
},{
color: 'red'
}]
}
},
series: [{
data: this.result
}]
};
});
}
options: Object;
in this case json data: [{"key":"Math","value":98},{"key":"Physics","value":78},{"key":"Biology","value":70},{"key":"Chemistry","value":90},{"key":"Literature","value":79}]
How can I split this data like there http://www.knowstack.com/webtech/charts_demo/highchartsdemo4.html