JSON response Object with changing keys/values - json

I have tried looking on many sites and browsed through many posts here, but still can't find what I am looking for, or at least could not implement it work. I have an API response where depending on the request parameters it either returns an object with an array of objects (which I am able to deal with), or an object with several objects that contain arrays within them. I was able to get the data from the simple form, but the multi-object containing object is kicking my butt. I am also doing this in Angular 4, just in case that makes a difference. The response is from the holiday api.
Below is the full response with no filtering params, minus a few objects, to not beat a dead horse.
{ "status": 200, "holidays": {
"2016-01-01": [
{
"name": "Durin's Day",
"date": "2016-01-01",
"observed": "2016-01-01",
"public": true
}
],
"2016-02-23": [
{
"name": "Founder's Day",
"date": "2016-02-23",
"observed": "2016-02-23",
"public": true
}
],
"2016-02-29": [
{
"name": "Leap Day",
"date": "2016-02-29",
"observed": "2016-02-29",
"public": false
}
],
"2016-03-20": [
{
"name": "Weasel Stomping Day",
"date": "2016-03-20",
"observed": "2016-03-20",
"public": false
}
],
"2016-04-05": [
{
"name": "First Contact Day",
"date": "2016-04-05",
"observed": "2016-04-05",
"public": false
}
],
"2016-04-06": [
{
"name": "Second Contact Day",
"date": "2016-04-06",
"observed": "2016-04-06",
"public": false
}
],
"2016-05-10": [
{
"name": "Whacking Day",
"date": "2016-05-10",
"observed": "2016-05-10",
"public": false
}
],
"2016-10-31": [
{
"name": "Harry Potter Day",
"date": "2016-10-31",
"observed": "2016-10-31",
"public": false
}
],
"2016-11-24": [
{
"name": "Hogswatch",
"date": "2016-11-24",
"observed": "2016-11-24",
"public": false
}
],
"2016-12-23": [
{
"name": "Festivus",
"date": "2016-12-23",
"observed": "2016-12-23",
"public": true
}
],
"2016-12-25": [
{
"name": "Decemberween",
"date": "2016-12-25",
"observed": "2016-12-25",
"public": false
},
{
"name": "Winter Veil",
"date": "2016-12-25",
"observed": "2016-12-26",
"public": true
}
]
} }
Here is the code used:
import { Component, OnInit, Input } from '#angular/core';
import { HolidayService } from '../holiday.service';
#Component({
selector: 'app-holiday',
templateUrl: './holiday.component.html',
styleUrls: ['./holiday.component.css']
})
export class HolidayComponent implements OnInit {
constructor(private _holiday: HolidayService) {
}
holidaysObj: any;
holidayArr: Array<{key: string, value: string}>;
ngOnInit() {
}
holidayParams(country,month){
this._holiday.getHolidays(country.value,month.value)
.subscribe(responseDa
ta => {
this.holidaysObj = responseData;
console.log(responseData);
});
this.convertObj(this.holidaysObj);
}
convertObj(obj : any){
for(const prop in obj){
if(obj.hasOwnProperty(prop)){
this.holidayArr.push(obj[prop]);
}
}
}
}
It works just fine when the response is called with filtering params, like 'month' and returns something like this:
{
"status": 200,
"holidays": [
{
"name": "Festivus",
"date": "2016-12-23",
"observed": "2016-12-23",
"public": true
},
{
"name": "Decemberween",
"date": "2016-12-25",
"observed": "2016-12-25",
"public": false
},
{
"name": "Winter Veil",
"date": "2016-12-25",
"observed": "2016-12-26",
"public": true
}
]
}

You can use a custom pipe to iterate your Objects, you could also extract the data from holidays from your response like:
.map(res => res.json().holidays)
but here I won't do it.
So let's create the custom pipe:
#Pipe({
name: 'keys'
})
export class KeysPipe implements PipeTransform {
transform(value: any, args?: any[]): any[] {
// check there is value to iterate
if(value) {
// create instance vars to store keys and final output
let keyArr: any[] = Object.keys(value),
dataArr = [];
// loop through the object,
// pushing values to the return array
keyArr.forEach((key: any) => {
dataArr.push(value[key]);
});
// return the resulting array
return dataArr;
}
}
}
and then you can use it in the template like:
<div *ngFor="let d of data?.holidays | keys">
<div *ngFor="let a of d">
{{a.name}}
{{a.date}}
<!-- rest of the properties -->
</div>
</div>
Here's a
Demo
UPDATE:
Alternatively, if you want to make your data to the same format as the other data you are receiving, you can manipulate the response. Like you mentioned, you need an if else statement first to check in which format the data is. In case the data is in the format like presented in question, you can do the following to reach the desired result:
.subscribe(data => {
// add statuscode
this.data = {status:data.status,holidays:[]}
let keyArr: any[] = Object.keys(data.holidays);
keyArr.forEach((key: any) => {
// push values of each holiday
this.data.holidays.push(data.holidays[key][0]);
});
})
Demo

Related

How can I fetch a particular data from nested array from JSON file in Angular by using params?

This is my JSON file.
{mood:
[ {
"id":"1",
"text": "Annoyed",
"cols": 1,
"rows": 2,
"color": "lightgreen",
"route":"/angry",
"musics": [
{
"id": "0",
"name": "English- Heaven's Peace",
"image": "images/music.png",
"link": "https://www.youtube.com/playlist?list=PLPfXrbtn3EgleopO8DiEdsNKgqYZZSEKF",
"descpription": "Tunes that soothe your pained soul",
"reviews": [
{
"name": "abc",
"rating": 4,
"review": "energetic",
"date": ""
}
]
},
{
"id": "1",
"name": "English- Hell's Fire",
"image": "images/music.png",
"link": "https://www.youtube.com/playlist?list=PLPfXrbtn3EgmZitRQf1X1iYwWW_nUF44L",
"descpription": "Beats that match the ones of your heart",
"reviews": [
{
"name": "abc",
"rating": 3.5,
"review": "energetic",
"date": ""
}
]
},
{
"id": "2",
"name": "Hindi",
"image": "images/music.png",
"link": "",
"descpription": "",
"reviews": [
{
"name": "abc",
"rating": 4,
"review": "energetic",
"date": ""
}
]
},
{
"id": "3",
"name": "Punjabi",
"image": "images/music.png",
"link": "https://www.youtube.com/playlist?list=PLPfXrbtn3Egnntch2thUO55YqPQgo4Qh7",
"descpription": "",
"reviews": [
{
"name": "abc",
"rating": 4,
"review": "energetic",
"date": ""
}
]
},
{
"id": "4",
"name": "Mix and Match",
"image": "images/music.png",
"link": "https://www.youtube.com/playlist?list=PLPfXrbtn3EglN5LVTETqH3ipRLfXmY6MB",
"descpription": "",
"reviews": [
{
"name": "abc",
"rating": 5,
"review": "energetic",
"date": ""
}
]
}
]
} ]
}
I have created angular services in a file name mood.services.ts
import { Injectable } from '#angular/core';
import { Mood } from '../shared/mood';
import { Observable, of } from 'rxjs';
import { delay } from 'rxjs/operators';
import { map, catchError } from 'rxjs/operators';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { baseURL } from '../shared/baseurl';
import { ProcessHTTPMsgService } from './process-httpmsg.service';
#Injectable({
providedIn: 'root'
})
export class MoodService {
constructor(private http: HttpClient,
private processHTTPMsgService: ProcessHTTPMsgService) { }
getMoods(): Observable<Mood[]> {
return this.http.get<Mood[]>(baseURL + 'moods')
.pipe(catchError(this.processHTTPMsgService.handleError));
}
getMood(id: number): Observable<Mood> {
return this.http.get<Mood>(baseURL+'moods/'+id)
.pipe(catchError(this.processHTTPMsgService.handleError));
}
getMoodIds(): Observable<number[] | any> {
return this.getMoods().pipe(map(moods => moods.map(mood => mood.id)))
.pipe(catchError(error => error));
}
getMusicIds(): Observable<number[] | any> {
return this.getMoods().pipe(map(musics => musics.map(music => music.id)))
}
}
And this is my musicdetail.component.ts file which will fetch the data of the particular music that is chosen.
import { Component, OnInit, Inject } from '#angular/core';
import { Mood } from '../shared/mood';
import { Music } from '../shared/music';
import { Review } from '../shared/review';
import { MoodService } from '../services/mood.service';
import { Params, ActivatedRoute } from '#angular/router';
import { Location } from '#angular/common';
import { switchMap } from 'rxjs/operators';
#Component({
selector: 'app-musicdetail',
templateUrl: './musicdetail.component.html',
styleUrls: ['./musicdetail.component.scss']
})
export class MusicdetailComponent implements OnInit {
mood : Mood;
music: Music;
musicIds: string;
errMess: string;
prev : string;
next : string;
review: Review;
constructor(private moodservice: MoodService,
private route: ActivatedRoute,
private location: Location,
#Inject('BaseURL') private BaseURL) { }
ngOnInit(): void {
this.route.params.pipe(switchMap((params: Params) => {return this.moodservice.getMood(params['id']);
}))
.subscribe(mood => {this.mood = mood;}, errmess => this.errMess = <any>errmess);
}
}
I have passed both mood.id and music.id when clicked in music.component.ts using '[routerLink]="['/musicdetails', mood.id, music.id]"`, on the list of music but I am unable to make logic to fetch particular music to display all its details. I am able to get mood-id using getMood(id) service but unable to do the same for music inside that mood.
WARNING:
your JSON data is wrong, Either you have missing single quote or double quote or 2nd bracket or third bracket. I don't know what you missed, its a long JSON file .
There is a JSON fixing website ( this one ) . I pasted your JSON and fixed it first.
Now I am writing this answer using correct version of your JSON (you can see it below)
So here it the answer:
The answer is simple - just use filter method to filter a particular property you need
.ts :
let jsonData =
{
"mood":[
{
"id":"1",
"text":"Annoyed",
"cols":1,
"rows":2,
"color":"lightgreen",
"route":"/angry",
"musics":[
{
"id":"0",
"name":"English- Heaven's Peace",
"image":"images/music.png",
"link":"https://www.youtube.com/playlist?list=PLPfXrbtn3EgleopO8DiEdsNKgqYZZSEKF",
"descpription":"Tunes that soothe your pained soul",
"reviews":[
{
"name":"abc",
"rating":4,
"review":"energetic",
"date":""
}
]
},
{
"id":"1",
"name":"English- Hell's Fire",
"image":"images/music.png",
"link":"https://www.youtube.com/playlist?list=PLPfXrbtn3EgmZitRQf1X1iYwWW_nUF44L",
"descpription":"Beats that match the ones of your heart",
"reviews":[
{
"name":"abc",
"rating":3.5,
"review":"energetic",
"date":""
}
]
},
{
"id":"2",
"name":"Hindi",
"image":"images/music.png",
"link":"",
"descpription":"",
"reviews":[
{
"name":"abc",
"rating":4,
"review":"energetic",
"date":""
}
]
},
{
"id":"3",
"name":"Punjabi",
"image":"images/music.png",
"link":"https://www.youtube.com/playlist?list=PLPfXrbtn3Egnntch2thUO55YqPQgo4Qh7",
"descpription":"",
"reviews":[
{
"name":"abc",
"rating":4,
"review":"energetic",
"date":""
}
]
},
{
"id":"4",
"name":"Mix and Match",
"image":"images/music.png",
"link":"https://www.youtube.com/playlist?list=PLPfXrbtn3EglN5LVTETqH3ipRLfXmY6MB",
"descpription":"",
"reviews":[
{
"name":"abc",
"rating":5,
"review":"energetic",
"date":""
}
]
}
]
}
]
} ;
// music - i can save here
let r = jsonData.mood[0].musics.filter(data => data.id == "2");
// music - or i can console.log it also
// i am comparing with 2 here - compare with your id number
// according to your need
console.log(jsonData.mood[0].musics.filter(data => data.id == "2"));
// in the same way you can search mood also
console.log(jsonData.mood.filter(data=> data.id == "1"));
to get something from parameter of url : follow this
there are multiple ways to get params from url
see this question : stackoverflow
see this blog : digitalocean

Angular dynamic forms created with JSON data

Dear reader. I am trying to make dynamic forms with Json data that has been red. The dynamic form is based on the example of Angular as seen here: https://angular.io/guide/dynamic-form
The edits I made are that I read data from an external Json file and try to load those instead of the hardcoded one in the file 'question.service.ts' as seen in the link.
This is how my Json file looks like:
{
"formInfo": {
"name": "test"
},
"fields": [
{
"controlType": "textbox",
"key": "firstName",
"label": "Voornaam",
"required": true,
"value": "Mark",
"order": 1
},
{
"controlType": "textbox",
"key": "surName",
"label": "Achternaam",
"required": true,
"order": 2
},
{
"controlType": "textbox",
"key": "emailAddress",
"label": "Email",
"required": false,
"order": 3
},
{
"controlType": "dropdown",
"key": "brave",
"label": "Beoordeling",
"required": "",
"order": 4,
"options": {
"solid": "Solid",
"great": "Great",
"good": "Good",
"unproven": "Unproven"
}
}
]
}
And my function to retrieve the data and return as observable (in question.service.ts) looks like:
getQuestions2() : Observable<QuestionBase<any>[]> {
let questions: QuestionBase<any>[] = [];
const exampleObservable = new Observable<QuestionBase<any>[]>((observer) =>
{
let url = "../assets/exampleData.json"
this.http.get(url).subscribe((data) => {
for (let x of data['fields']){
if (x.controlType == "textbox"){
let textboxItem = new TextboxQuestion({
key: x.key,
label: x.label,
value: x.value,
order: x.order
})
questions.push(textboxItem);
}
else if (x.controlType == "dropdown"){
let dropDownItem = new DropdownQuestion({
key: x.key,
label: x.label,
value: x.value,
options: x.options,
order: x.order
})
questions.push(dropDownItem);
}
}
})
observer.next(questions.sort((a, b) => a.order - b.order));
})
return exampleObservable;
}
and the code that connects the service with the frontend looks like this:
export class AppComponent implements OnInit {
questions: any[];
constructor(private service: QuestionService) {
this.getaSyncData();
//this.questions = this.service.getQuestions();
//console.log(this.questions);
}
getaSyncData(){
this.service.getQuestions2()
.subscribe((data) => this.questions = data);
console.log(this.questions);
}
I solved this finally for those who will have similar issues in the future
I was not able to load forms into the html even though I was correctly reading the data out of the JSON file and printing it in the console. I added a *ngIf in the div where you load in your data. In the example of Angular.io its in the template on App.component.html. Yes, it was this simple.

Set next step for the waterfall dialogue in Microsoft BotBuilder NodeJS SDK

I am using Microsoft Bot Framework for my facebook messenger bot. I want to load the dialog data from json files instead of hard coding in the js file. I would like to configure the next step in the dialog, based on result from the "current" step, which is part of the json file configuration, something like this.
{
"name": "welcome",
"type": "waterfall",
"steps": [
{
"id": 0,
"data": [
{
"type": "text",
"value": "Hey, It's nice to meet you."
},
{
"type": "quickReplies",
"value": "What do you want to do next?",
"options": [
{
"text": "some option 1",
"value": "option1"
},
{
"text": "some option 2",
"value": "option2"
}
]
}
],
"next": [
{
"result": "option1",
"action": "goto step 2"
},
{
"result": "option2",
"action": "goto step 5"
}
]
}
]
}
I would like to process all the incoming messages and respond with correct dialog or correct step in the dialog for the user.
I am trying something like this;
handleMessage = function (session) {
var step = session.dialogData["BotBuilder.Data.WaterfallStep"] || 0;
// check response data from previou step and identify the next step.
// set the waterfall step id
session.dialogData["BotBuilder.Data.WaterfallStep"] = 2;
session.send("Hello");
}
var bot = new builder.UniversalBot(connector, function (session) {
handleMessage(session);
})
.set('storage',tableStorage);
With this code, I am always getting step as zero for session.dialogData["BotBuilder.Data.WaterfallStep"] even after setting this to a different number.
Also, as soon as I set the waterfall step number, all other state data that is stored in my table storage for this conversation is gone.
Storage data before setting waterfall step:
{
"BotBuilder.Data.SessionState": {
"callstack": [
{
"id": "*:/",
"state": {
"BotBuilder.Data.WaterfallStep": 0
}
},
{
"id": "*:welcome",
"state": {
"BotBuilder.Data.WaterfallStep": 1
}
},
{
"id": "BotBuilder:prompt-text",
"state": {
"options": {
"prompt": {
"type": "message",
"agent": "botbuilder",
"source": "facebook",
"address": {
"id": "mid.$cAAAlr-0LRH9niO21L1hV6hs83GuJ",
"channelId": "facebook",
"user": {
"id": "XXXX",
"name": "XXXX"
},
"conversation": {
"isGroup": false,
"id": "XX"
},
"bot": {
"id": "XXX",
"name": "XXX"
},
"serviceUrl": "https://facebook.botframework.com"
},
"text": "what do you want to next"
//ignored for simplicity
},
"promptAfterAction": true,
"libraryNamespace": "*"
},
"turns": 0,
"lastTurn": 1517594116372,
"isReprompt": false
}
}
],
"lastAccess": 1517594112740,
"version": 0
}
}
After I set the waterfall step:
{
"BotBuilder.Data.SessionState": {
"callstack": [
{
"id": "*:/",
"state": {
"BotBuilder.Data.WaterfallStep": 2
}
}
],
"lastAccess": 1517602122416,
"version": 0
}
}
Interestingly the step number is saved to the database (but in session state) but my "session" variable do not have this value anywhere. Also, even after configuring custom state service, the serviceUrl is still https://facebook.botframework.com which I thought is the default state service used if there is no state service set for the bot.
Per your code, as your bot actually contains only one waterfall step: handleMessage(session);, which raised your issue. You can consider to create multiple dialogs from json configration instead of complex waterfall steps.
Here is my quick test, for your information:
const json = `
[{
"name": "welcome",
"type": "waterfall",
"steps": [
{
"id": 0,
"data": [
{
"type": "text",
"value": "Hey, It's nice to meet you."
},
{
"type": "quickReplies",
"value": "What do you want to do next?",
"options": [
{
"text": "some option 1",
"value": "option1"
},
{
"text": "some option 2",
"value": "option2"
}
]
}
],
"next": [
{
"result": "option1",
"action": "dialog2"
},
{
"result": "option2",
"action": "dialog3"
}
]
}
]
},{
"name":"dialog2",
"type": "waterfall",
"steps": [
{
"data": [
{
"type": "text",
"value": "Hey, this is dialig2."
}]
}
]
},{
"name":"dialog3",
"type": "waterfall",
"steps": [
{
"data": [
{
"type": "text",
"value": "Hey, this is dialig3."
}]
}
]
}]
`;
const generateSignleStep = (step) => {
return (session, args, next) => {
step.forEach(sentence => {
switch (sentence.type) {
case 'quickReplies':
let choices = sentence.options.map(item => {
return item.value
});
let card = new builder.ThumbnailCard(session)
.text(sentence.value)
.buttons(sentence.options.map(choice => new builder.CardAction.imBack(session, choice.value, choice.text)))
let message = new builder.Message(session).addAttachment(card);
builder.Prompts.choice(session, message, choices);
break;
case 'text':
default:
session.send(sentence.value)
break;
}
})
}
}
const generatenextAction = (actions) => {
return (session, args, next) => {
const response = args.response;
actions.map(action => {
if (action.result == response.entity) {
session.beginDialog(action.action);
}
})
}
}
const generateWaterfallSteps = (steps) => {
let waterfall = [];
steps.forEach(step => {
waterfall.push(generateSignleStep(step.data));
if (step.next) {
waterfall.push(generatenextAction(step.next));
}
});
return waterfall;
}
var bot = new builder.UniversalBot(connector);
const jsonobj = JSON.parse(json);
jsonobj.forEach(dialog => {
bot.dialog(dialog.name, generateWaterfallSteps(dialog.steps))
.triggerAction({
matches: new RegExp(dialog.name, "g")
})
});
The result is:

Angular 2: How to modify json feed before giving it to template

From json I get this:
{
"name": "Leonardo",
"weapon": "sword"
},
{
"name": "Donatello",
"weapon": "stick"
},
{
"name": "Michelangelo",
"weapon": "nunchucks"
},
{
"name": "Raphael",
"weapon": "sai"
}
But for template I want to insert one extra field dynamically:
{
"name": "Leonardo",
"weapon": "sword"
"is_leader": "true"
},
{
"name": "Donatello",
"weapon": "stick"
"is_leader": "false"
},
{
"name": "Michelangelo",
"weapon": "nunchucks"
"is_leader": "false"
},
{
"name": "Raphael",
"weapon": "sai"
"is_leader": "false"
}
But I can't even get component to return the observable (says it's undefined, but renders ok in template). So far I have this in my component.
constructor(private dataService: DataService) {
this.dataSubscription = this.dataService.getTestData().subscribe(res => this.allData = res);
}
You should modify the data from .map()
Here is the logic how you can achieve that will current given code :
.subscribe(res => {
this.allData = res.map(e => {
e['is_leader'] = true; // as per your rule;
return e;
});
});
With HttpClient which came with Angular 4.3+, you could use interceptors (HttpIntercept) to intercept, filter and/or modify you incoming JSON feed. A bit of googling shows how to setup interceptors and use them like here for example.

How to get json value from Angular2 app

I need to get values from a JSON file which is served from fake-json-server.
To be precise, I need an exact value, e.g. I need to get all "type": "values" where group is Air.
I'm using Angular2 with TypeScript and here is a part of the code where I'm doing a get request in the TransformerService file:
getVehicleGroups(groupName: string) {
return this.http.get(`${this.apiUrl}/vehicleTypes?group=${groupName}`)
.map((res: Response) => res.json() as VehicleTypes[]).catch(this.handleError);
}
Exported class:
export class VehicleTypes {
// vehicleGroup: string;
vehicleType: string;
vehicleModel: string;
}
And here I'm calling that method in the separate file:
getVehicleGroups() {
return this.transformersService.getVehicleGroups(this.vehicleGroup)
.subscribe((vehicleTypes => this.vehicleTypes = vehicleTypes));
}
The url of the fake-server "http://localhost:3000/vehicleTypes" and this is the code from db.json on that server (url):
[
{
"group": "Air",
"type": "Plane",
"model": "F-22"
},
{
"group": "Air",
"type": "Plane",
"model": "Sukhoi"
},
{
"group": "Air",
"type": "Plane",
"model": "MiG"
},
{
"group": "Air",
"type": "Helicopter",
"model": "Apache"
},
{
"group": "Air",
"type": "Helicopter",
"model": "Kamov"
}
{
"group": "Sea",
"type": "Boat",
"model": "Sailboat"
},
{
"group": "Sea",
"type": "Boat",
"model": "Jetboat"
},
{
"group": "Sea",
"type": "Submarine",
"model": "Standard"
},
{
"group": "Land",
"type": "Car",
"model": "Camaro"
},
{
"group": "Land",
"type": "Car",
"model": "AMG GT R"
},
{
"group": "Land",
"type": "Car",
"model": "Lamborghini"
},
{
"group": "Land",
"type": "Truck",
"model": "Unimog"
},
{
"group": "Land",
"type": "Truck",
"model": "Western Star 5700"
}
]
I need to mention, all my files are set well. I don't get any errors, I'm just not getting the right values..
I need to get all "type": "values" where group is Air
First you need do filter your json result to get Air group only.
You can apply observable filter
getVehicleGroups(groupName: string) {
return this.http.get(`${this.apiUrl}/vehicleTypes?group=${groupName}`)
.filter(data => data.group === "Air")
.map((res: Response) => res.json() as VehicleTypes[]).catch(this.handleError);
}
Second your VehicleTypes model variable names are different with json response so how will angular convert your json array into VehicleTypes array. you need change VehicleTypes class or your backend code send match variables name.
export interface VehicleTypes {
type: string;
model: string;
}
Adjust the brackets of your method.
From:
getVehicleGroups() {
return this.transformersService.getVehicleGroups(this.vehicleGroup)
.subscribe((vehicleTypes => this.vehicleTypes = vehicleTypes));
}
To:
getVehicleGroups() {
return this.transformersService.getVehicleGroups(this.vehicleGroup)
.subscribe((vehicleTypes) => this.vehicleTypes = vehicleTypes);
}
Map the data with your model:
Option 1: Change the model to match the json data.
export class VehicleTypes {
type: string;
model: string;
}
Option 2: Change the json properties at service level, right after converting to json.
getVehicleGroups(groupName: string) {
return this.http.get(`${this.apiUrl}/vehicleTypes?group=${groupName}`)
.map((res: Response) => res.json().map(res => new VehicleTypes(res.type, res.model)).catch(this.handleError);
}
and you would need to create a constructor for the VehicleTypes.
You do not need a class in this case, a type interface will suffice since you don't have (or seem to need) any methods in your vehicle, you're only using it for type assertion.
A class exists in the emitted JavaScript incurring unnecessary overhead, whereas an interface provides type safety without emitting classes to JavaScript: it's only used by the type-checker in tsc and then discarded.
export interface VehicleTypes {
// vehicleGroup: string;
vehicleType: string;
vehicleModel: string;
}
Declare the type that your service returns:
getVehicleGroups(groupName: string): Observable<VehicleTypes[]> {
return this.http.get(`${this.apiUrl}/vehicleTypes?group=${groupName}`)
.map(res.json)
.catch(this.handleError);
}
And consume it in your Component as:
// Assert the type vehicleTypes expects
vehicleTypes: <VehicleTypes>[];
getVehicleGroups() {
return this.transformersService.getVehicleGroups(this.vehicleGroup)
.subscribe(vehicleTypes => this.vehicleTypes = vehicleTypes);
}
Note that you don't need the (res: Response) assertion in the chain from http.get: that's what get is typed to return anyway so the type-checker already knows what to expect. Since you can remove the parameter, you can make the chain even shorter, as you did with .catch.