This question already has answers here:
Angular 5+ cannot save result form observable response
(4 answers)
Closed 4 years ago.
I am working on a barcode scanning app with angular.
The number of the barcode returns a json containing a "box" object. How can i parse the box json to a box class in angular?
This is my existing code:
//Injectable Dataservice
export class BoxService {
//url vars
urlBegin:string = "url";
urlEinde:string = "/last-order";
url:string;
test;
constructor(#Inject(HttpClient) private http: HttpClient){
}
getBox(barcode):Observable<Box>{
this.url = this.urlBegin + barcode + this.urlEinde;
return this.http.get<Box>(this.url);
}
}
// My component using the service showBox() is the method using the service
import { Component, OnInit, Inject, Injectable } from '#angular/core';
import { BoxService } from '../BoxService';
import { Box } from '../Box';
#Component({
selector: 'app-Data',
templateUrl: './Data.component.html',
styleUrls: ['./Data.component.css']
})
export class DataComponent implements OnInit {
uitkomst:String;
box:Box;
constructor(private boxService:BoxService) { }
zoekBarcode(barcode):void{
this.uitkomst = "ik heb info over deze barcode: " + barcode;
this.showBox(barcode);
}
showBox(barcode){
this.boxService.getBox(barcode).subscribe(data => this.box = data);
console.log(this.box.boxNumber.toString());
}
ngOnInit() {
}
}
// Box Class
import { Contentline } from "./Contentline";
export class Box {
boxNumber: number;
status: number;
shipTo: string;
shipToName: string;
contentLines: Contentline[];
}
//Contentline class
export class Contentline {
articleIdCustomer: string;
description: string;
orderId: string;
orderLineId: string;
quantity: number;
uom: string;
closet: any;
shelf: any;
deliveryDate: string;
}
My JSON string looks like this:
{
"boxNumber": 13100973,
"contentLines": [
{
"articleIdCustomer": "112050",
"description": " Nutraclear naaldvrije connector",
"departmentName": null,
"deliveryDate": "2018-06-26T22:00:00Z"
},
{
"articleIdCustomer": "101512",
"description": " LIJN INFUUSVERLENG 400CM 1,5 MM PE/PVC",
"departmentName": null,
"deliveryDate": "2018-06-27T22:00:00Z"
},
{
"articleIdCustomer": "101053",
"description": " LIJN INFUUS 700CM 1X2,1MM 25ST",
"departmentName": null,
"deliveryDate": "2018-06-27T22:00:00Z"
},
{
"articleIdCustomer": "101053",
"description": " LIJN INFUUS 700CM 1X2,1MM 25ST",
"departmentName": null,
"deliveryDate": "2018-07-03T22:00:00Z"
},
{
"articleIdCustomer": "101053",
"description": " LIJN INFUUS 700CM 1X2,1MM 25ST",
"departmentName": null,
"deliveryDate": "2018-07-04T22:00:00Z"
},
{
"articleIdCustomer": "101386",
"description": " DOP AFSLUIT ENTERALE SPUIT ENFIT (PER 8",
"departmentName": null,
"deliveryDate": "2018-06-25T22:00:00Z"
}
],
"status": 3,
"otherDepartments": []
}
If you are interested in typesafe object creation consider following Box class constructor (I simplified it to single field):
interface iBox { /* You will get this structure from HTTP get */
articleIdCustomer: string,
}
class Box implements iBox {
articleIdCustomer: string,
constructor(iBox: IBox) {
this.articleIdCustomer =
(typeof(iBox.articleIdCustomer) !== 'undefined') ? iBox.articleIdCustomer : undefuned
}
}
and then at recieving JSON object from web:
this.boxService.getBox(barcode).subscribe((data: iBox) => this.box = new Box(data));
If some of fiels are mandatory, you can throw Errors in constructor
Rewrite you below the line of code
this.boxService.getBox(barcode).subscribe(data => this.box = data);
as
this.boxService.getBox(barcode).subscribe(data:Box => this.box = data);
you can give type to data it automatically cast all your object accordingly.
Related
Hi I'd like to create a small authentication service in my angular application, I have a JSON file containing the information about my users:
{
"Users": [
{
"type":"teacher",
"id":0,
"name":"TEACHER ONE",
"login":"tone",
"password":"d450c5dbcc10db0749277efc32f15f9f"
},
{
"type":"student",
"id":1,
"name":"STUDENT ONE",
"login":"sone",
"password":"ec80dcc5a3eab73a4f128b66c1e4b92a"
},
{
"type":"student",
"id":2,
"name":"STUDENT TWO",
"login":"stwo",
"password":"62e73bf0deb1871860702b064106f1dc"
}
]
}
and here's what I try for my authentifiaction
import { Injectable } from '#angular/core';
import * as users from '../assets/Users.json';
import { clientType } from "./clientType";
#Injectable({
providedIn: 'root'
})
class user {
$type: clientType; //I put a dollar so equals won't compare this property
$id: number; //I put a dollar so equals won't compare this property
$name: string; //I put a dollar so equals won't compare this property
login: string;
password: string;
constructor(type: clientType, id: number, name: string, login: string, password: string) {
this.$type = type;
this.$id = id;
this.$name = name;
this.login = login;
this.password = password;
}
}
export class AuthService {
private userList: /*don't know what to put*/ = /*don't know what to put*/;
constructor() { }
consultData( ): void{
}
returnUsers() {
return this.userList;
}
}
I'm trying to get an array of users using my JSON file but I don't know how to extract the JSON object as user objects, can someone help me finding how ?
I have a JSON object and I want to give the values of the properties to 4 of my variables using Angular, which are the following:
authorText : string;
titleText : string;
durationText : string;
genreText : string;
And here is the JSON:
"{"n":{
"_id":1101,
"labels":[
"Song"
],
"properties":{
"duration":"214000",
"author":"Shawn Mendes",
"genre":"pop",
"title":"In My Blood"
}
}
}"
I tried using this and similar solutions to this:
Object.keys(editData).forEach(function (key) {
console.log(key);
if(key === "author"){
this.authorText = editData[key];
}
console.log( key , editData[key] );
});
But the key is always 0 for some reason.
EDIT
Added the image of the JSON:
The string I printed before was done as following : Saving it as global variable and then using JSON.stringify(temp1);.
You can use this:
const { duration, author, genre, title } = this.editData[0].n.properties;
this.song = {
authorText: author,
titleText: title,
durationText: duration,
genreText: genre
};
Here, we're destructuring the properties from the properties key and just assigning them to the song Object's keys one by one.
A better thing to do would be just to name the fields as duration, author, genre, and title. Then you can simply do something like this:
export interface Song {
author: string;
title: string;
duration: string;
genre: string;
}
And in your function:
this.song = { ...editData[0].n.properties };
Here, we're using the spread operator(...) to spread the properties object's keys and assign them to the song property on your Component Class.
Here's a Sample StackBlitz for your ref.
You can just do this:
this.song = this.editData.n.properties;
I have a stackblitz demonstrating it here: https://stackblitz.com/edit/angular-udmdqr
The basic code is here:
import { Component, Input } from '#angular/core';
#Component({
selector: 'hello',
template: `<h1>Hello {{song.author}}!</h1>`,
styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent {
song: Song;
editData = {
"n": {
"_id": 1101,
"labels": [
"Song"
],
"properties": {
"duration": "214000",
"author": "Shawn Mendes",
"genre": "pop",
"title": "In My Blood"
}
}
}
constructor() {
this.song = this.editData.n.properties;
}
}
export interface Song {
duration: string;
author: string;
genre: string;
title: string
}
So I am trying to learn some basic Angular by creating an application that fetches and displays the current weather of a location using OpenWeather API.
This is what I have in my code currently:
app.component.ts:
import { Component } from '#angular/core';
import { WeatherService } from './weather.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [WeatherService]
})
export class AppComponent {
title = 'Ng-Weather';
cityName: string;
weather: Weather;
constructor(private weather: WeatherService) { }
search() {
this.weather.getWeatherbyName(this.cityName)
.subscribe(res => this.weather = res);
console.log(this.weather);
}
}
weather.service.ts:
import { Injectable } from '#angular/core';
import { Http, Response, URLSearchParams } from '#angular/http';
import { Observable } from 'rxjs';
import { Weather } from './weather';
#Injectable()
export class WeatherService {
APIurl = "http://api.openweathermap.org/data/2.5/weather";
Appid = "xxx";
weather: Weather;
constructor(private http: Http) { }
getWeatherbyName(name: string): Observable<any> {
let myParams = new URLSearchParams();
myParams.append('appid', this.Appid);
myParams.append('q', name);
return this.http.get(this.APIurl , { search: myParams} )
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
this.weather.city = body.name;
this.weather.description = body.weather[0].main;
this.weather.temp = body.main.temp;
console.log(this.weather);
}
private handleError(error: Response | any) {
console.error(error.message || error);
return Observable.throw(error.message || error);
}
}
weather.ts:
export class Weather {
city: String;
description: String;
temp: String;
}
So basically I am trying to map a JSON returned from OpenWeather API and get only some parts of the data and not the whole thing. The JSON returned is like following:
{
"coord":{
"lon":80.28,
"lat":13.09
},
"weather":[
{
"id":802,
"main":"Clouds",
"description":"scattered clouds",
"icon":"03n"
}
],
"base":"stations",
"main":{
"temp":303.15,
"pressure":1008,
"humidity":79,
"temp_min":303.15,
"temp_max":303.15
},
"visibility":6000,
"wind":{
"speed":3.1,
"deg":210
},
"clouds":{
"all":40
},
"dt":1504805400,
"sys":{
"type":1,
"id":7834,
"message":0.0017,
"country":"IN",
"sunrise":1504744074,
"sunset":1504788314
},
"id":1264527,
"name":"Chennai",
"cod":200
}
When the above code is executed, I get this error:
weather.service.ts:32 Cannot set property 'city' of undefined
Also how do I return an observable of type Weather and return that variable weather and catch it on the app.component.ts?
You are not creating an instance of the weather object before assigning its properties. You can do that explicitly like this:
this.weather = new Weather();
this.weather.city = body.name;
this.weather.description = body.weather[0].main;
this.weather.temp = body.main.temp;
console.log(this.weather);
OR
You can do something like this:
this.weather = {
city: body.name,
description: body.weather[0].main,
temp: body.main.temp
}
console.log(this.weather);
And to answer the second part of your question, you should be able to do this:
getWeatherbyName(name: string): Observable<Weather> {
// your other code
}
private extractData(res: Response) {
// your other code
return this.weather;
}
And to answer the third part of your question ... Observables are asynchronous. This means that they do not immediately return a value. Rather they provide for definition of a callback function that is executed when the data is returned. That means that the data is undefined until the data is returned and the callback function is executed.
So if you want to access the returned data in your code, you need to do in WITHIN the callback function. Like this:
search() {
this.weather.getWeatherbyName(this.cityName)
.subscribe(res => {
this.weather = res;
console.log(this.weather);
});
}
I'm new in Angular 2 and I'm quite lost. I have a JSON web service responding to /rest/alertsDashboard. It returns something like:
{
"total": {
"totalOperations": 2573,
"totalOperationsAlert": 254,
"totalOperationsRisk": 34
},
"alerts": [
{
codAlert: "L1",
description: "Alert 1",
value: 1
},
{
codAlert: "L2",
description: "Alert 2",
value: 2
},
...
]
}
So I defined a DashboardComponent component and a AlertDashboardService service. I would like, for example, to display totalOperations and totalOperationsAlert. I don't know if I'm doing it in a correct way.
In dashboard.component.ts I have:
...
#Component({
selector: 'app-dashboard',
template: `
<p>{{totalAlertsDashboard.totalOperations}}</p>
<p>{{totalAlertsDashboard.totalOperationsAlert}}</p>
...
`
})
export class DashboardComponent implements OnInit {
totalAlertsDashboard: TotalAlertsDashboard;
alertsDashboard: AlertDashboard[];
constructor(private alertsDashboardService: AlertsDashboardService) { }
ngOnInit() {
this.alertsDashboardService.get().then(
response => {
this.totalAlertsDashboard = response.totalAlertsDashboard;
this.alertsDashboard = response.alertsDashboard;
}
);
}
}
In alerts-dashboard.service.ts I have:
...
export class AlertsDashboard {
totalAlertsDashboard: TotalAlertsDashboard;
alertsDashboard: AlertDashboard[];
}
export class TotalAlertsDashboard {
totalOperations: number;
totalOperationsAlert: number;
totalOperationsRisk: number;
}
export class AlertDashboard {
codAlert: string;
description: string;
value: number;
}
#Injectable()
export class AlertsDashboardService {
private headers = new Headers({ 'Content-Type': 'application/json' });
private url = environment.urlAPI + '/rest/alertsDashboard';
constructor(private http: Http) { }
get(): Promise<AlertsDashboard> {
var vm = this;
let params = new URLSearchParams();
return vm.http.get(vm.url, { search: params })
.toPromise()
.then(response => {
var responseJson: AlertsDashboard = response.json() ;
console.log(responseJson); // it prints the JSON correctly
return responseJson;
});
}
}
I hope you can help me with that.
try this :
ngOnInit() {
this.alertsDashboardService.get().then(
response => {
this.totalAlertsDashboard = response.total;
this.alertsDashboard = response.alerts;
}
);
}
In alerts-dashboard.service.ts
export class AlertsDashboard {
total: TotalAlertsDashboard;
alerts: AlertDashboard[];
}
template :
<p>{{totalAlertsDashboard?.totalOperations}}</p>
I am trying to query the wagtail API that will return JSON in a very unfriendly format.
{
"id": 3,
"meta": {
"type": "home.HomePage",
"detail_url": "http://localhost:8000/api/v1/pages/3/"
},
"parent": null,
"title": "Homepage",
"body": "<h2>cool an h2 fgf</h2>",
"main_image": {
"id": 1,
"meta": {
"type": "wagtailimages.Image",
"detail_url": "http://localhost:8000/api/v1/images/1/"
}
},
"header_image": {
"id": 1,
"meta": {
"type": "wagtailimages.Image",
"detail_url": "http://localhost:8000/api/v1/images/1/"
}
},
"show_in_menus": true,
"full_url": "/media/images/Background-4.original.jpg"
}
All I really want from that is a class like this.
export class HomePage {
id: number;
title: string;
body: string;
full_url: string;
}
But whenever I get back from the data back from my service and try and log it, it is undefined.
Is there any way for me to ignore the fields I don't want from a JSON in typescript?
The service I am using is:
import { Injectable } from '#angular/core';
import {Http, Response} from '#angular/http';
import {Observable} from "rxjs";
import {HomePage} from "./HomePage";
#Injectable()
export class HomePageService {
constructor(private http: Http){
}
getHomePage(GUID: number): Observable<HomePage>{
return this.http
.get("http://localhost:8000/api/v1/pages/" + GUID + "/")
.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, we 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);
}
}
And the component:
import {Component, OnInit, OnDestroy} from '#angular/core';
import {HomePageService} from './home-page.service';
import {ActivatedRoute} from '#angular/router';
import {HomePage} from "./HomePage";
#Component({
selector: 'app-home-page',
templateUrl: './home-page.component.html',
styleUrls: ['./home-page.component.css'],
providers: [HomePageService]
})
export class HomePageComponent implements OnInit, OnDestroy{
id: number;
private sub: any;
public homePage: HomePage;
errorMessage: string;
constructor(private homePageService : HomePageService, private route: ActivatedRoute) {
}
ngOnInit() {
this.sub = this.route.params.subscribe(params => {
this.id = +params['id'];
});
this.homePageService.getHomePage(this.id)
.subscribe(
homePage => this.homePage = new HomePage(homePage),
error => this.errorMessage = <any>error,
() => console.log(this.homePage.full_url)
);
console.log(this.id);
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
homePage => this.homePage = new HomePage(homePage) - in your code I don't see a constructor defined for HomePage class. So when you pass the homePage object to it, nothing happens. Try this:
export class HomePage{
id: number;
title: string;
body: string;
full_url: string;
constructor(homePageObj: any)
{
if (homePageObj)
{
this.id = homePageObj.id;
this.title = homePageObj.title;
this.body = homePageObj.body;
this.full_url = homePageObj.full_url;
}
}
}