Saving data in angular 8 with subscribe [duplicate] - javascript

This question already has answers here:
How do I return the response from an Observable/http/async call in angular?
(10 answers)
Closed 3 years ago.
Hello I have a problem with saving data in subscribe with angular 8.
when i make this this.service.getAll().subscribe(response => console.log(this.itemList = response))
and print itemList the array is empty, i try to print the response in the subscribe and response have data.
I tried to make print in subscribe and print of local array in this way :
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { ItemService } from 'src/service/item.service';
import { Item } from 'src/DTO/item';
#Component({
selector: 'app-crafting-dashboard',
templateUrl: './crafting-dashboard.component.html',
styleUrls: ['./crafting-dashboard.component.css']
})
export class CraftingDashboardComponent implements OnInit{
itemList: Item[] = [];
constructor(private router: Router, protected service: ItemService) {
}
ngOnInit() {
this.service.getAll().subscribe(response => console.log("Reponse:" + response));
console.log("Constrol print" + this.itemList);
}
getAll(){
}
}
i've noted that in console appear first the console.log("Constrol print" + this.itemList);
and after the print of subscribe. It could be this the problem?!?!?
this is my service (i made an abstract service and in the specific service I add the specific method for an entity:
import { Service } from './service';
import { Observable } from 'rxjs';
import { HttpClient } from '#angular/common/http';
export class AbstractService<DTO> implements Service<DTO> {
type: string = '';
port: string = '8080';
constructor(protected http: HttpClient){}
getAll(): Observable<DTO[]> {
return this.http.get<DTO[]>('http://localhost:' + this.port + '/' + this.type + '/getAll');
}
read(id: number): Observable<DTO> {
return this.http.get<DTO>('http://localhost:' + this.port + '/' + this.type + '/read?id=' + id);
}
insert(dto: DTO): Observable<DTO> {
return this.http.post<DTO>('http://localhost:' + this.port + '/' + this.type + '/insert', dto);
}
update(dto: DTO): Observable<DTO> {
return this.http.put<DTO>('http://localhost:' + this.port + '/' + this.type + '/update', dto);
}
delete(id: number): Observable<any> {
return this.http.delete('http://localhost:' + this.port + '/' + this.type + '/delete?id=' + id);
}
}
The back-end is written in java with spring

In this code:
ngOnInit() {
this.service.getAll().subscribe(response => console.log("Reponse:" + response));
console.log("Constrol print" + this.itemList);
}
The callback response => console.log("Reponse:" + response) is delayed, it executes when receiving the HTTP response. This explains the behavior you observed ("Constrol print" being shown before "Reponse:").
If you have to do something with the data you receive, do it in the callback, and not in ngOnInit:
this.service.getAll().subscribe(response => {
console.log("Reponse:" + response);
//Whatever you want to do with the response and the variables assigned to the response goes here
});

Do like this
this.service.getAll().subscribe(response => {
this.itemList=response;
console.log("Console print" + this.itemList);
});

Related

Angular HTTPClient POST body not sending

Currently I am trying to POST a name, email and message from an angular frontend to a php script running in the same nginx server which then runs phpmailer to send an email containing the name, email and message. Here is the code so far:
import { Component, OnInit } from '#angular/core';
import { Email } from './email';
import {ContactService} from './contact.service';
import {HttpClient, HttpHeaders} from '#angular/common/http';
import {NgForm} from '#angular/forms';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded'
})
};
const email = new Email('', '', '');
#Component({
selector: 'app-contact',
templateUrl: './contact.component.html',
styleUrls: ['./contact.component.css'],
providers: [ContactService]
})
export class ContactComponent implements OnInit {
email = new Email('', '', '');
constructor(private http: HttpClient) { }
sendEmail(form: NgForm) {
const value = form.value;
const senderName = value.name;
const senderEmail = value.email;
const senderMessage = value.message;
this.sendMail(senderName, senderEmail, senderMessage);
}
sendMail(senderName, senderEmail, senderMessage) {
console.log(senderName + ' ' + senderEmail + ' ' + senderMessage);
this.http.post('https://ruffstuffcostumes.tk/assets/scripts/email.php',
{
name: senderName,
email: senderEmail,
message: senderMessage,
},
httpOptions
)
.subscribe(
(val) => {
console.log('POST call successful value returned in body',
val);
},
response => {
console.log('POST call in error', response);
},
() => {
console.log('The POST observable is now completed.');
});
}
ngOnInit() {
}
}
When I ran the POST request through postman to check it, it ran perfectly well and sent out the email containing the required elements, however when I execute a query with this script, even though the console.log(senderName + ' ' + senderEmail + ' ' + senderMessage) does show the values, it doesn't seem to post them in the body at all, and all I get back is the fact that even though a mail was sent, it was sent without any of those values in the body of the email.
Could it be cross-origin problems (and if so what would be the best way to get around that?), or am I just doing some stupid mistake?
Just for completeness. I solved the problem by switching to sending JSON data and parsing it on the php side

Angular 2 - Cannot read property '...' of undefined

Very new to Angular. I checked similar questions but they either dive into specifics or I just don't understand the solutions.
The actual error:
"Cannot read property 'idPlanet' of undefined at Object.eval [as updateRenderer] (PlanetComponent.html:11)"
The issue:
planetDetail.idPlanet is undefined most probably?
Suspect:
getPlanetDetail()
planet.component.html:
<div class="col-sm-9">
ID: {{ planetDetail.idPlanet }}
</div>
planet.component.ts:
import {
Component,
OnInit
} from '#angular/core';
import { Planet } from './planet';
import { PlanetService } from './planet.service';
#Component({
selector: 'planets',
templateUrl: './planet.component.html'
})
export class PlanetComponent implements OnInit {
private planets: Planet[];
private planetDetail: Planet;
constructor(
private planetService: PlanetService
) {}
public ngOnInit(): void {
this.getPlanetDetail();
this.getPlanets();
}
public getPlanets() {
this.planetService.getPlanets()
.subscribe(
(planets) => this.planets = planets
);
}
public getPlanetDetail() {
this.planetService.getPlanetDetail()
.subscribe(
(planets) => this.planetDetail = planets
);
}
}
planet.service.ts:
import { Injectable } from '#angular/core';
import { Headers, Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { Planet } from './planet';
#Injectable()
export class PlanetService {
private planetsUrl = 'http://localhost/index.php/api/planet/'; // URL to web api
// Injecting the http client into the service
constructor(private http: Http) {}
public getPlanets(): Observable<Planet[]> {
return this.http.get(this.planetsUrl + 'planets/id_sol/1')
.map(this.parseData)
.catch(this.handleError);
}
public getPlanetDetail(): Observable<Planet> {
return this.http.get(this.planetsUrl + 'planet/id_planet/1')
.map(this.parseData)
.catch(this.handleError);
}
private parseData(res: Response) {
let body = res.json();
if (body instanceof Array) {
return body || [];
} else {
return body.post || {};
}
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error); // for demo purposes only
return Promise.reject(error.message || error);
}
}
I'm at a loss tbh, I tried to build my getPlanetDetail() method from getPlanets() which works fine. Should I use a promise?
I'm having a hard time figuring out where exactly I can put console.log() to debug. I'm using angular-starter kit from Github.
Thanks for your time.
edit 1: the api outputs {"idPlanet":"1","name":"Earth"}
As the request is asynchronous sometime the value will not be fetched from the server when the page loads, therefore, the planetDetail is undefined. in order to avoid this you can use add '?' between planetDetail and idPlanet. that prints only if it has the value
ID: {{ planetDetail?.idPlanet }}
If you want to print the result or error
public getPlanetDetail() {
this.planetService.getPlanetDetail()
.subscribe(
(planets) => {
console.log(planets);
this.planetDetail = planets
},
error => {console.log(error);}
);
}
Since your response is {"idPlanet":"1","name":"Earth"}, try the following:
public getPlanetDetail(): Observable<Planet> {
return this.http.get(this.planetsUrl + 'planet/id_planet/1')
.map(res => res.json())
.catch(this.handleError);
}
my friend to debug if your 'planetDetail' is populated, just add 'console.log (planetDetail)' in the 'subscribe' method. Follow the example below.
public getPlanetDetail() {
this.planetService.getPlanetDetail()
.subscribe(
(planets) => this.planetDetail = planets
);
}
public getPlanetDetail() {
this.planetService.getPlanetDetail()
.subscribe(
(planets) => this.planetDetail = planets, (err) => (err), () => console.log(this.palnetDetail)
);
}
More about subscribe()
subscribe(function(response) {
console.log("Success Response" + response)
},
function(error) {
console.log("Error happened" + error)
},
function() {
console.log("the subscription is completed")
});

Nested Observables behaving differently in Ionic2/Angular2 App

I am creating an ionic login module, where in there are 2 observables , 1 inside another, Not sure if this is the correct way of implementation,
Here I am trying to call getHTTP() method, get a string, if the string is not empty then set it in ionic-storage varaible and then verify before logging in
Since Observables are async - getHTTP() is getting completed after the flow of login(credentials) , Help me out
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
import {Observable} from 'rxjs/Observable';
import {Headers} from '#angular/http';
import { Response } from '#angular/http';
import { Storage } from '#ionic/storage';
export class User {
name: string;
password: string;
url: string;
constructor(name: string, password: string, url: string) {
this.name = name;
this.password = password;
this.url = url;
}
}
/*
Generated class for the AuthService provider.
See https://angular.io/docs/ts/latest/guide/dependency-injection.html
for more info on providers and Angular 2 DI.
*/
#Injectable()
export class AuthService {
currentUser: User;
data = '';
constructor(public http: Http,private storage: Storage) {
console.log('Hello AuthService Provider');
}
// Make a call to Get CSRF and check if we have access
public getHTTP(credentials) {
let responseCSRF ;
const headers: Headers = new Headers();
headers.append('Authorization', 'Basic ' + btoa(credentials.user + ':' + credentials.password));
headers.append('Content-Type', 'application/json');
console.log(headers);
console.log('Clearing cache');
this.storage.set('CSRF', '');
this.storage.set('Auth',btoa(credentials.user + ':' + credentials.password));
this.storage.set('url', credentials.url);
//return
responseCSRF = this.http.get('http://' + credentials.url +'/Windchill/servlet/rest/security/csrf', {
headers: headers
}).map((response: Response) => response.json());
//console.log(typeof(responseCSRF))
responseCSRF.subscribe(x => {
console.log('CSRF ->' + x.items[0].attributes.nonce)
this.data = x.items[0].attributes.nonce;
if(typeof this.data!='undefined' && this.data) {
this.storage.set('CSRF', this.data);
}
});
return responseCSRF;
}
public login(credentials) {
if (credentials.user === null || credentials.password === null || credentials.url === null ) {
return Observable.throw("Please insert credentials ");
} else {
return Observable.create(observer => {
// At this point make a request to your backend to make a real check!
let access = false;
this.getHTTP(credentials).subscribe (
(resBody) => console.log('Boby is '+resBody),
error => console.error('Error from auth-service: ' + error))
, () => console.log('Completed!' + 'Auth' );
this.storage.get('CSRF').then((val) => {
console.log('Your CSRF is'+ val);
if(val!='undefined') {
access = true;
}
});
observer.next(access);
observer.complete();
});
}
}
public getUserInfo() : User {
return this.currentUser;
}
public logout() {
return Observable.create(observer => {
this.currentUser = null;
observer.next(true);
observer.complete();
});
}
}
In the Console
Headers {_headers: Map(2), _normalizedNames: Map(2)}
auth-service.ts:49 Clearing cache
auth-service.ts:57 pluck -->[object Object]
auth-service.ts:83 Your CSRF is
auth-service.ts:59 CSRF ->RkPYp+UtGGMRB+8NJHCr9rJ6WhBHdIVCfim585xXKgZ1TKUmf3v39tBqVRkjSb93dgWi4oF3KF4rNts0c3frktUdIFokNNVrMSGM47V3KwQhP8A5ARKr5rBsaxtmOtI=
auth-service.ts:78 Boby is [object Object]
Try to put your storage.get logic inside subscription handler:
return Observable.create(observer => {
// At this point make a request to your backend to make a real check!
let access = false;
this.getHTTP(credentials).subscribe(
(resBody) => {
console.log('Boby is ' + resBody);
this.storage.get('CSRF').then((val) => {
console.log('Your CSRF is' + val);
if (val != 'undefined') {
access = true;
}
observer.next(access);
observer.complete();
});
},
error => console.error('Error from auth-service: ' + error),
() => console.log('Completed!' + 'Auth'));
});

How to use angular 2 service which returns http promise

I have a trouble with angular 2 here.
I use service that return promise but when i try to retrive the response i got an error.
i was read this this stact question
this my code.
this is HotelService.ts
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
//rxjs promises cause angular http return observable natively.
import 'rxjs/add/operator/toPromise';
#Injectable()
export class HotelService {
private BASEURL : any = 'http://localhost:8080/hotel/';
constructor(private http: Http) {}
load(): Promise<any> {
return this.http.get(this.BASEURL + 'api/client/hotel/load')
.toPromise()
.then(response => {
response.json();
//console.log(response.json());
})
.catch(err => err);
}
}
this Hotel.ts (component)
import { Component, OnInit } from '#angular/core';
import { NavController } from 'ionic-angular';
import { HotelService } from '../../providers/hotel/hotelservice';
import { AboutPage } from '../../pages/about/about';
import { HotelDetailPage } from '../../pages/hoteldetail/hotel';
#Component({
selector: 'page-home',
templateUrl: 'home.html',
providers: [HotelService]
})
export class HomePage implements OnInit {
public searchBoxActive = false;
public hotels: any;
constructor(
private navCtrl: NavController,
private hotelServ: HotelService
) { }
load() {
this.hotelServ.load()
.then(res => {
this.hotels = res;
console.log(res); //why the rest is undefined?
console.log('ini component');
},
err => err);
}
toggleSearchBox() {
if (this.searchBoxActive == false) {
this.searchBoxActive = true;
} else {
this.searchBoxActive = false;
}
}
showAbout() {
this.navCtrl.setRoot(AboutPage);
}
pushDetail(evt, id) {
this.navCtrl.push(HotelDetailPage)
}
ngOnInit(): void {
this.load();
}
}
I have no idea.
You need to return response.json() from promise then callback:
load(): Promise<any> {
return this.http.get(this.BASEURL + 'api/client/hotel/load')
.toPromise()
.then(response => {
return response.json();
})
.catch(err => err);
}
The dfsq's answer is correct, but for the completeness' sake, below is an example according to the official Angular.io recommendations:
load(): Promise<any> {
return this.http.get(this.BASEURL + 'api/client/hotel/load')
.toPromise()
.then(response: Response) => response.json() || {})
.catch((error: Response | any) =>
{
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();
return Promise.reject(errMsg);
});
}
Key differences:
handle empty response in the then;
pretty up the error before throwing it further.

Value become null for this in Promise callback

I am using the following code value of this become null when i call it inside the then function here is the code. Am i doing something wrong or it is like this or there is any work around to resolve this issue
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Headers, RequestOptions } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { CanActivate, Router } from '#angular/router';
import { AuthService } from '../services/auth.service';
import { WebAPISettings } from '../services/webapisettings.service';
#Injectable()
export class LoginService {
//_ngWEBAPISettings: WebAPISettings;
//_authService: AuthService;
constructor(private http: Http, private ngWEBAPISettings: WebAPISettings, private authService: AuthService) {
//this._ngWEBAPISettings = ngWEBAPISettings;
//this._authService = authService;
}
public login(username: string, password: string): Promise<any> {
let data = "grant_type=password&username=" + username + "&password=" + password;
let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
let options = new RequestOptions({ headers: headers });
try {
debugger;
return this.http.post(this.ngWEBAPISettings.apiServiceBaseUri + "token", data, options)
.toPromise()
.then(function (res: Response) {
debugger;
let body = res.json();
//let _authService: AuthService = new AuthService();
this.authService.fillAuthDataFromLogin(body);
//this.router.navigate(['/Home']);
return body.data || {};
})
.catch(this.handleError);
}
catch (error) {
console.log(error);
}
}
private extractData() {
}
private handleError(error: any) {
debugger;
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);
}
}
and i am debugging it in the chrome here is the screenshot please help me in fixing it.
after using the arrow function same thing check the screen shot
one thing to mention i am using Angular2 RC4.
You could use an arrow function to be able to use the lexical this:
return this.http.post(this.ngWEBAPISettings.apiServiceBaseUri + "token", data, options)
.toPromise()
.then((res: Response) => { // <-----
(...)
});
This way, this will correspond to the instance of the LoginService service.
See this doc for more details:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Categories

Resources