Angular : ERROR SyntaxError: Unexpected token < in JSON at position 0 - json

Hi I need help I created an angular service but when I want to view the data from my json file it shows me this error, I tried a lot of unsuccessful solution
app.component.ts
import {Component, OnInit} from '#angular/core';
import {Car} from './domain/car';
import {CarService} from './service/carservice';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [CarService]
})
export class AppComponent implements OnInit {
cars1: Car[];
constructor(private carService: CarService) { }
ngOnInit() {
this.carService.getCarsSmall().subscribe(cars => this.cars1 = cars);
}
}
carservice.ts
#Injectable()
export class CarService {
private jsonUrl = './cars-smalll.json';
constructor(private http: Http) {}
getCarsSmall(): Observable<Car[]> {
return this.http.get(this.jsonUrl)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body.data || { };
}
private handleError (error: Response | any) {
// In a real world app, you might use a remote logging infrastructure
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
}
cars-smalll.json
[
{
"brand": "VW",
"year": 2012,
"color": "Orange",
"vin": "dsad231ff"
},
{
"brand": "Audi",
"year": 2011,
"color": "Black",
"vin": "gwregre345"
},
{
"brand": "Renault",
"year": 2005,
"color": "Gray",
"vin": "h354htr"
}
]
thank you in advance.

Besides using the correct path suggested in comments, your problem is that you are trying to extract data from something that does not exist. Take a look at your json, it's an array. But in your extractData-function you are trying to extract data from an object data, which is of course not present in your JSON. So change that function to:
private extractData(res: Response) {
let body = res.json();
// return just the response, or an empty array if there's no data
return body || [];
}
This should do it, as well as correcting the path of the JSON file.

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

How can I access the json key value with help of typescript variable?

Json File
"Tamil": {
"Name": "பெயர்",
"Email": "மின்னஞ்சல்",
"Phoneno": "தொலைபேசி எண்",
"Password": "கடவுச்சொல்",
"CPassword": "கடவுச்சொல்லை உறுதிப்படுத்தவும்",
"Register": "பதிவு",
"Cancel": "ரத்துசெய்"
},
Ts File
import {Component, OnInit} from '#angular/core';
import * as data from '../home/lang.json';
#Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {
public language;
public value;
constructor() {
this.value = 'Tamil';
this.language = data[this.value].Name;
alert(this.language);
}
ngOnInit() {
}
}
Output
ERROR Error: "Uncaught (in promise): TypeError: _home_lang_json__WEBPACK_IMPORTED_MODULE_2___namespace[this.value] is undefined
HomePage#http://localhost:8100/home-home-module.js:128:9
HomePage_Factory#ng:///HomePage/ɵfac.js:5:10
But When I try this possibility is working fine:
this.language = data["Tamil"].Name;
But while trying this
this.language = data[this.value].Name;
It's Showing that error.
The only mistake you are doing is accessing Malayalam which does not exist in your JSON file, add Malayalam and it will work fine.
Some code fine tune I am doing which might help.
replace
import * as data from '../home/lang.json'
to coz TypeScript > 2.9 has a simplest way to do that
import data from '../home/lang.json
JSON File
{
"Tamil": {
"Name": "பெயர்",
"Email": "மின்னஞ்சல்",
"Phoneno": "தொலைபேசி எண்" ,
"Password": "கடவுச்சொல்",
"CPassword": "கடவுச்சொல்லை உறுதிப்படுத்தவும்",
"Register":"பதிவு",
"Cancel" : "ரத்துசெய்"
},
"Malayalam": {
"Name": "பெயர் m",
"Email": "மின்னஞ்சல் m",
"Phoneno": "தொலைபேசி எண் m" ,
"Password": "கடவுச்சொல் m",
"CPassword": "கடவுச்சொல்லை உறுதிப்படுத்தவும் m",
"Register":"பதிவு m",
"Cancel" : "ரத்துசெய் m"
}
}
Component
constructor() {
this.value = "Malayalam";
this.language = data[this.value].Name;
alert(this.language)
}
Hope this works.
The dynamic import returns Promise.
use case:
import * as data from '../home/lang.json'
#Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {
public language;
public value;
constructor() {
this.value = "Malayalam";
this.language = data.default <=== add `default`
[this.value]?.Name;
alert(this.language)
}
ngOnInit() {
}
}
You can print data in the console to see its structure.
You can make on http call to fetch the json data
constructor(
private httpClient: HttpClient
) { }
this.httpClient.get('../home/lang.json')
.subscribe((res) => {
this.data = res;
});
Or simply you can read the file as
this.data= require('../home/lang.json');
CheckThis
You can the value by
this.result =this.data[this.language].Name
Sample code
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template:
`<input [(ngModel)]="language" (ngModelChange)="onSelection()" >
<h1>{{ result ? result : data[language].Name }}</h1>`,
})
export class AppComponent {
language = 'Tamil';
result='';
public data = {
"Tamil": {
"Name": "பெயர்",
"Email": "மின்னஞ்சல்",
"Phoneno": "தொலைபேசி எண்" ,
"Password": "கடவுச்சொல்",
"CPassword": "கடவுச்சொல்லை உறுதிப்படுத்தவும்",
"Register":"பதிவு",
"Cancel" : "ரத்துசெய்"
} ,
"Malayalam": {
"Name": "Name Malayalam",
"Email": "Email malayalam",
"Phoneno": "தொலைபேசி எண்" ,
"Password": "கடவுச்சொல்",
"CPassword": "கடவுச்சொல்லை உறுதிப்படுத்தவும்",
"Register":"பதிவு",
"Cancel" : "ரத்துசெய்"
}
}
onSelection() {
this.result =this.data[this.language].Name
}
}
I think you forgot to add Malayalam language in your json.
If it can be happen that language may not present in your json then you should do like this
this.language = data[this.value] ? data[this.value].Name : '';
Instead of blank you can use default language too. If defualt language available in your json file then you can use like this.
this.language = data[this.value] ? data[this.value].Name : data['defaultLanguage'].Name ;

recuperate fields of a json

I have a json like this :
[ {
"id": 1,
"libraryName": "lib1",
"bookName": "book1",
"bookPrice": 250.45,
"unitSold": 305
},
{
"id": 2,
"libraryName": "lib1",
"bookName": "book2",
"bookPrice": 450.45,
"unitSold": 150
},
{
"id": 3,
"libraryName": "lib1",
"bookName": "book3",
"bookPrice": 120.25,
"unitSold": 400
}]
I want to recuperate all the bookNames of this json in a list without creating the method getBookNames (because I want a standard way for any field of the json)
So, in the component.ts I used :
sales:any;
getSale () {
this.service.getSales().subscribe(data=> {this.sales = data,
console.log(this.sales.bookName)
})
}
It gives me undefined object in the console ! How can I solve this without creating a method getBookNames() ?
This is my class :
export interface Sale {
id: number
bookname : string
Libraryname: string
Bookprice : number
Unitsold : number
}
This is my service:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Sale } from './Sale';
#Injectable({
providedIn: 'root'
})
export class MyserviceService {
constructor(private http: HttpClient) { }
getSales () {
return this.http.get<Sale>("http://localhost:8081/sales/all")
}
}
The data obtained from the API is an array. So you could use array map() function to obtain a list of all the properties from the elements. Try the following
sales: any;
unitsSold = [];
getSale () {
this.service.getSales().subscribe(data=> {
this.sales = data,
console.log(data.map(item => item.bookName)); // <-- output: ['book1', 'book2', 'book3'];
console.log(data.map(item => item.id)); // <-- output: [1, 2, 3];
this.unitsSold = data.map(item => item.unitSold); // <-- [305, 150, 400]
});
}
I don't see anything lost here to recuperate.

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