How get clear http-request data in component? - javascript

Service get json-data from backend:
constructor(private http: Http) { };
getUsers(): Observable<any> {
return this.http.get('http://127.0.0.1:8000/app_todo2/users_list');
};
In the component, this data is processed:
ngOnInit() {
this.getAllUsersData();
}
private getAllUsersData(): void {
this.usersService.getUsers().subscribe(
data => {
this.allUsersData = JSON.parse(data.json());
console.log(this.allUsersData);
})
};
But i need processed this data in service. And i need get in component clear data:
private getAllUsersData(): void {
this.usersService.getUsers().subscribe(
data => {
this.allUsersData = data;
console.log(this.allUsersData);
})
};
please help me.

Map your data on service:
getUsers(): Observable<any> {
return this.http.get('http://127.0.0.1:8000/app_todo2/users_list')
.map(data => data.json());
}
then:
private getAllUsersData(): void {
this.usersService.getUsers().subscribe(
data => {
this.allUsersData = data;
console.log(this.allUsersData);
})
};

Related

Several flatmaps cause error on saving (Typescript)

I have Angular component to upload files to server.
Here is save method of it
private saveFileAndData(): void {
this._propertyService
.createOrEditProperty(this.property)
.pipe(
flatMap(r => this._fileUploadService.uploadFiles(this.getUploadUrl(r), this.files)),
flatMap(r => this._fileUploadService.uploadFiles(this.getFloorPlanUploadUrl(r), this.floorPlans)),
finalize(() => {
this.saving = false;
})
)
.subscribe(() => {
this.notify.info(this.l('SavedSuccessfully'));
this.close();
this.modalSave.emit(null);
});
}
When I was having one flat map, all was okay, now I need to load different files via save. So I have 2 flatMaps. But now I have this error
If I leave just one flat map, all okay.
Here is fileUpload service
#Injectable()
export class FileUploadService {
constructor(private _http: HttpClient) {}
uploadFiles(url: string, filesToUpload: any[]): Observable<any> {
if (filesToUpload.length) {
const formData: FormData = new FormData();
for (let file of filesToUpload) {
formData.append('file', file);
}
let headers = new HttpHeaders();
return this._http.post(url, formData, { headers: headers });
}
return of(null);
}
}
How I can solve it?

Angular constructor doesn't set a local variable before ngOnInit() is called

I am struggling with calling the backend from angular. When I create a component I also get the parameter "category" from the URL like this:
export class ProductsComponent{
productList = []
category = ""
$params;
$products;
constructor(
private products: ProductsService,
private route: ActivatedRoute
){}
ngOnInit() {
this.$params = this.route.params.subscribe(params => {
this.category = params['category']
});
this.$products = this.products.products(this.category).subscribe(
productList => {
this.productList = productList.result
},
err => {
console.log(err)
}
)
}
ngOnDestroy(){
// DON'T FORGET TO UNSUBSCRIBE!!!
this.$params.unsubscribe();
this.$products.unsubscribe();
}
}
This works well, but now in the ProductsService, where I call the http.get I think it is not working fine.
#Injectable()
export class ProductsService {
constructor(private http: HttpClient, private router: Router) {}
public products(category: string): Observable<any> {
return this.http.get(`/products/getallproducts`, {headers: {'Content-Type': 'application/json'}, params: {'category': category}})
}
}
Because when I try to log the req.body.category in the backend, it says it is null. But it is not, it is the right value.
This is what I am trying to do in Node:
products.get(('/getallproducts'), (req, res) => {
let category = req.body.category;
console.log("REQ" + req.body)
if(category === "all") {
ProductModel.findAll()
.then(result => {
res.json({result: result})
})
.catch(err => {
res.json({error: err})
})
} else {
ProductModel.findAll({
where: {
productsubcategory: category
}
})
.then(result => {
res.json({result: result})
})
.catch(err => {
res.json({error: err})
})
}
})
Review this article: Todd MoTTo: Angular constructor versus ngOnInit
Then move your constructor code into your ngOnInit method.
// Add these;
$params;
$products;
constructor(
private products: ProductsService,
private route: ActivatedRoute
){}
ngOnInit() {
this.$params = this.route.params.subscribe(params => {
this.category = params['category']
});
this.$products = this.products.products(this.category).subscribe(
productList => {
this.productList = productList.result
},
err => {
console.log(err)
});
}
ngOnDestroy(){
// DON'T FORGET TO UNSUBSCRIBE!!!
this.$params.unsubscribe();
this.$products.unsubscribe();
}
Update: I see what you're doing now. It appears to be a bit backwards to me. First you are loading the component, then going to GET some backend data. If you are routing to something new that requires some data, then try a resolver. With a resolver, you can fetch new data on route change. It is up to you if you want to pause the resolver until you get data (and have a spinner on the link that was clicked), or show a loading screen and wait for it. But the resolver will load when the route is loaded and it will publish the result. Then listen for the resolver Observable in the component.
// In Routes
{
path: 'products/:category',
component: YourComponent,
resolve: {
data: ProductsResolver
}
},// rest of routes.
#Injectable()
export class ProductsResolver implements Resolve<any> {
constructor(
private http: HttpClient
){}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any>|Promise<any>|any {
return this.http.get('/products/getallproducts',
{
headers: {
'Content-Type': 'application/json'
},
params: {
'category': route.params.category
}
});
}
And the component then would be...
$products;
constructor(
private route: ActivatedRoute
){}
ngOnInit() {
this.$products = this.route.data.subscribe(productList => {
this.productList = productList.result;
},
err => {
console.log(err)
});
}
ngOnDestroy(){
this.$products.unsubscribe();
}

TypeError: result is null when subscribing to a post request

When I'm trying to subsrcibe to a post request, it always returns the TypeError: result is null
I'm using a Angular CLI that connects with a Spring boot application, with a simple login page. Where I want to save the header of my response in local storage
This is the stacktrace:
"LoginComponent.prototype.login/<#webpack-internal:///../../../../../src/app/components/login/login.component.ts:32:13\nSafeSubscriber.prototype.__tryOrUnsub#webpack-internal:///../../../../rxjs/_esm5/Subscriber.js:245:13\nSafeSubscriber.prototype.next#webpack-internal:///../../../../rxjs/_esm5/Subscriber.js:192:17\nSubscriber.prototype._next#webpack-internal:///../../../../rxjs/_esm5/Subscriber.js:133:9\nSubscriber.prototype.next#webpack-internal:///../../../../rxjs/_esm5/Subscriber.js:97:13\nMapSubscriber.prototype._next#webpack-internal:///../../../../rxjs/_esm5/operators/map.js:88:9\nSubscriber.prototype.next#webpack-internal:///../../../../rxjs/_esm5/Subscriber.js:97:13\nFilterSubscriber.prototype._next#webpack-internal:///../../../../rxjs/_esm5/operators/filter.js:92:13\nSubscriber.prototype.next#webpack-internal:///../../../../rxjs/_esm5/Subscriber.js:97:13\nMergeMapSubscriber.prototype.notifyNext#webpack-internal:///../../../../rxjs/_esm5/operators/mergeMap.js:156:13\nInnerSubscriber.prototype._next#webpack-internal:///../../../../rxjs/_esm5/InnerSubscriber.js:27:9\nSubscriber.prototype.next#webpack-internal:///../../../../rxjs/_esm5/Subscriber.js:97:13\nonLoad#webpack-internal:///../../../common/esm5/http.js:2310:21\nZoneDelegate.prototype.invokeTask#webpack-internal:///../../../../zone.js/dist/zone.js:421:17\nonInvokeTask#webpack-internal:///../../../core/esm5/core.js:4939:24\nZoneDelegate.prototype.invokeTask#webpack-internal:///../../../../zone.js/dist/zone.js:420:17\nZone.prototype.runTask#webpack-internal:///../../../../zone.js/dist/zone.js:188:28\nZoneTask.invokeTask#webpack-internal:///../../../../zone.js/dist/zone.js:496:24\ninvokeTask#webpack-internal:///../../../../zone.js/dist/zone.js:1517:9\nglobalZoneAwareCallback#webpack-internal:///../../../../zone.js/dist/zone.js:1543:17\n"
This is my login.service.ts:
const httpOptions = { headers: new HttpHeaders({'Content-type': 'application/json'}) };
#Injectable() export class LoginService {
private loginUrl = 'https://music-makers.herokuapp.com/login';
constructor(private http: HttpClient) { }
public login(user: User): Observable<any> {
return this.http.post(this.loginUrl, user, httpOptions); }
And my login.components.ts:
export class LoginComponent implements OnInit {
model: any = {};
constructor(private loginService: LoginService, public router: Router) {
}
ngOnInit() {
}
login() {
const user = <User>({
email: this.model.email,
password: this.model.password,
});
console.log('email: ' + user.email + '\npass: ' + user.password);
this.loginService.login(user)
.subscribe(
result => {
// Handle result
localStorage.setItem('Authorization', result.headers.get('Authorization'));
console.log(result);
},
error => {
// Handle error
console.log('Error');
},
() => {
console.log('complete');
// No errors, route to new page
}
);
}
}
Your service should be use map() to return as an observable collection
public login(user: User): Observable<any> {
return this.http.post(this.loginUrl, user, httpOptions)
.map(responce => <any>responce)
.catch(error => {
return Observable.throw(error);
});
}

How do I load data from an API into an array in Angular 2?

So last week I started learning AngularJS, only to realize that I'm better off learning Angular 2 instead. After much reading and tinkering with sample apps on Plunker, I'm finally ready to dive into Angular 2. Last week with AngularJS I was able to create a simple app that retrieves data from an API and turns that into a navigation menu. So this week I am attempting to port that code to Angular 2.
I can't say that it was easy, but after much fiddling I found that the reason it was not working was that it was not even pulling the data. Below is my code for the service that pulls the data.
./src/app/navigation.service.ts
import { NavItem } from './navigation.model';
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class NavService {
sections: NavItem[] = [];
categories: NavItem[] = [];
constructor(private http: Http) {
}
loadSections() {
//var headers = new Headers();
//headers.append('Content-Type', 'application/json');
this.http
.get('http://localhost:15557/api/navigation/sections/list')
.map(res => {
return res.json()
})
.subscribe(
data => {
this.sections = data;
},
err => this.logError(err),
() => console.log("Loaded all sections")
);
}
loadCategories(id) {
this.http
.get('http://localhost:15557/api/navigation/categories/' + id)
.map(res => res.json())
.subscribe(
data => this.categories = [data],
err => this.logError(err),
() => console.log("Loaded categories in section with id " + id)
);
}
logError(err) {
console.error('There was an error: ' + err);
}
}
./src/app/navigation.model.ts
export class NavItem {
// I am never going to use int unless I need to do math operations //
id: string;
name: string;
pid: string;
slug: string;
constructor(id: string, name: string, pid: string, slug: string) {
this.id = id;
this.name = name;
this.pid = pid;
this.slug = slug;
}
}
./src/app/navigation.component.ts
import { Component } from '#angular/core';
import { NavItem } from './navigation.model';
import { NavService } from './navigation.service';
#Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.css']
})
export class NavComponent {
public section: NavItem;
constructor(private service: NavService) { }
ngOnInit() {
this.service.loadSections();
}
}
What am I doing wrong with this code?
I have never used a service like that before. Maybe your implematation has a simple error, but here is how I always implement a service in angular. :)
Service
getSomething() {
return this.http.get('your-api-url').map(res => {
return res.json()
});
}
Component
makeRequest() {
this.service.getSomething().subscribe(data => {
this.variable = data;
}, err => {
console.log("error :/");
});
}

trying to call MVC Get Action from Angular 2 with typescript

I have a simple MVC Get method as below to get a Customer Id from the Session
[HttpGet]
public string GetCustomerId()
{
return Session["CUSTOMERID"].ToString();
}
If I hit this URL directly in the browser
http://localhost/myApp/Home/GetCustomerId I can set a breakpoint int the method and it gets hit and I get the value returned.
However, I need to call the method from my Client code which is Angular 2 written in typescript. My Typescript method is as below - I cannot get it to hit the MVC Breakpoint even though I am logging the exact same URL as above to the console.
public getCustomerIdFromSession() {
console.log('get customer from session called');
let srv = this.environmentService.getCurrentEnvironment();
let httpOrHttps = '';
if (srv === AppSettings.ENV_LOCALHOST) {
httpOrHttps = AppSettings.URL_HTTP;
}
else {
httpOrHttps = AppSettings.URL_HTTPS;
}
let baseUrl = httpOrHttps + srv + AppSettings.URL_GET_CUST_FROM_SESSION;
console.log(baseUrl); //this logs - http://localhost/myApp/Home/GetCustomerId
return this.http.get(baseUrl)
.catch(this.handleError);
}
public handleError(error: Response) {
console.log("error");
return Observable.throw(error.json() || 'Server Error');
}
**UPDATE To include entire Typescript service
import { Injectable, Output, EventEmitter } from '#angular/core';
import { Http, Response, RequestOptions, Headers } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { EnvironmentService } from '../common/environment.service';
import { AppSettings } from '../common/app-settings';
#Injectable()
export class SessionService {
#Output() public gSession: EventEmitter<any> = new EventEmitter();
private sessionTime: number = 1500000; // 25 minute
constructor(private http: Http, private environmentService: EnvironmentService) {
}
public setValue(isLoading: boolean): void {
this.gSession.emit(isLoading);
}
public getValue(): any {
return this.gSession;
}
public startSession(): void {
this.getCustomerIdFromSession();
let timeoutId = setTimeout(() => {
this.setValue(true);
}, this.sessionTime);
}
public getCustomerIdFromSession() {
console.log('get customer from session called');
let srv = this.environmentService.getCurrentEnvironment();
let httpOrHttps = '';
if (srv === AppSettings.ENV_LOCALHOST) {
httpOrHttps = AppSettings.URL_HTTP;
}
else {
httpOrHttps = AppSettings.URL_HTTPS;
}
let baseUrl = httpOrHttps + srv + AppSettings.URL_GET_CUST_FROM_SESSION;
console.log(baseUrl); //this logs - http://localhost/myApp/Home/GetCustomerId
return this.http.get(baseUrl)
.catch(this.handleError);
}
public handleError(error: Response) {
console.log("error");
return Observable.throw(error.json() || 'Server Error');
}
public extractData(res: Response) {
console.log("In extract method");
let body = res.json();
console.log(body);
if (body) {
return body.data || body;
} else {
return {};
}
}
}
You are not mapping the response.
return this.http
.get(baseUrl)
.map(this.extractData)
.catch(this.handleError);
private extractData(res: Response) {
let body = res.json();
if (body) {
return body.data || body;
} else {
return {};
}
}
You have to map the response and process it with json() if you know that will be a JSON or with text(). Usually will be JSON.
I took the liberty of adding a response handler such as extractData. You could just json() the response directly if you wanted.

Categories