make REST call with typescript - rest

I installed the "sb admin 2" dashboard with html5/angular2.
This sample works with typescript. To instanciate charts, the file charts.compenent.ts defines the class and then defines the charts attributes and data as follows
import { Component, OnInit} from '#angular/core';
#Component({
moduleId: module.id,
selector: 'chart-cmp',
templateUrl: 'chart.component.html'
})
export class ChartComponent implements OnInit {
ngOnInit() {
var container:any = $('#container');
container.highcharts({
chart: {
type: 'area'
},
...................................
In my case, I want to get the date from a restfull service.
Can you help me to do this please??
any input will help

Make sure you have the correct imports,
import {Http, Response, URLSearchParams} from '#angular/http';
This is how to make a get request,
Get Request
saveProfile(model: Profile, isValid: boolean) {
let params: URLSearchParams = new URLSearchParams();
// set params to go to URL
params.set('email', model.email);
params.set('first_name', model.first_name);
return this.http.get('url/path/here/dont/forget/port',
{ search: params })
.map((res: Response) => res.json())
.subscribe((res) => {
console.log(res);
// Map the values in the response to useable variables
this.auth.user.email = res.user.email;
this.auth.user.first_name = res.user.first_name;
});
}
}
Post Request
How to make a post request,This is a popular post request used in the auth0 library. You can find that here
authenticate(username, password) {
let creds = JSON.stringify({ username: username.value, password: password.value });
let headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.post('http://localhost:3001/sessions/create', creds, {
headers: headers
})
.subscribe(
data => {
this.saveJwt(data.json().id_token);
username.value = null;
password.value = null;
},
err => this.logError(err.json().message),
() => console.log('Authentication Complete')
);
}
These examples will get a response from the server. If you want to do some more technical things like get the new data to update in the view, you will have to create an observable. If I were you I would get this down then when you need to understand observable you can incorporate that.

Related

Using angular 4 to send form-data

Hi I'm building a WordPress theme and I need to use contact form 7 plugin on it, but I can't figure out the correct way to send the form data to the plugin.
here is my post service:
import {
Injectable
} from '#angular/core';
import {
HttpClient,
HttpHeaders
} from '#angular/common/http';
#Injectable()
export class FormsService {
constructor(private http: HttpClient) {}
postForm(url, form) {
return this.http.post(url, form, {
headers: new HttpHeaders().set('Content-Type', 'multipart/form-data'),
})
}
}
and the component part that use the service:
onSubmit() {
const fd = new FormData();
fd.append('your-name', this.name);
fd.append('your-email', this.email);
fd.append('your-message', this.message);
fd.append('your-subject', this.sumbject);
const url = `/wp-json/contact-form-7/v1/contact-forms/${this.form_id}/feedback`;
this.sendMsg.postForm(url, fd).subscribe(
data => {
console.log(data);
},
err => console.log({
error: err
})
)
this.submitted = true;
}
At this point the server response that the message was submitted ok, but when I go to the WP admin page, non of the field get the values.
But If I use postman with this url and params the form all works as I want.
I also found another solution that works but its not the angular way as I want to be.
the solution
onSubmit() {
const url = `/wp-json/contact-form-7/v1/contact-forms/${this.form_id}/feedback`;
this.submitted = true;
}
sendData(url) {
let XHR = new XMLHttpRequest();
const FD = new FormData();
FD.append('your-name', this.name);
FD.append('your-email', this.email);
FD.append('your-message', this.message);
FD.append('your-subject', this.subject);
// Define what happens on successful data submission
XHR.addEventListener('load', function(event) {
alert('Yeah! Data sent and response loaded.');
});
// Define what happens in case of error
XHR.addEventListener('error', function(event) {
alert('Oups! Something went wrong.');
});
// Set up our request
XHR.open('POST', url);
// Send our FormData object; HTTP headers are set automatically
XHR.send(FD);
}
I found my solution, the problem was on the headers definitions of my service, the correct way is:
postForm(url, body) {
var headers = new HttpHeaders();
headers.append('Content-Type', 'application/form-data');
return this.http.post(url, body, {headers: headers })
}

Angular 2 data service

I'm building an observable data service based on the following article: https://coryrylan.com/blog/angular-2-observable-data-services
In the article he used an array as an example, here I will use the user object since I'm developing the user service.
Here's what I got:
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Events, SqlStorage, Storage } from 'ionic-angular';
import { Subject } from 'rxjs/Subject';
export interface DataStore {
user: Object
}
#Injectable()
export class UserService {
private baseUrl: string;
private storage: Storage;
private _user$: Subject<Object>;
private dataStore: DataStore;
constructor(
private http: Http
) {
this.baseUrl = 'http://localhost:3000';
this.storage = new Storage(SqlStorage);
this._user$ = <Subject<Object>>new Subject();
this.dataStore = {
user: { name: '' }
};
}
set user$(user: Object) {
this.storage.set('user', JSON.stringify(user));
this.dataStore.user = user;
this._user$.next(this.dataStore.user);
}
get user$() {
return this._user$.asObservable();
}
loadUser() {
return this.storage.get('user').then(
((user: string): Object => {
this.dataStore.user = JSON.parse(user);
this._user$.next(this.dataStore.user);
return this.dataStore.user;
})
);
}
login(accessToken: string) {
return this.http
.post('http://localhost:3000/login', { access_token: accessToken })
.retry(2)
.map((res: Response): any => res.json());
}
logout(): void {
this.storage.remove('user');
}
}
To authenticate I call the login() function and set the user data if everything ok.
this.userService.login(this.data.accessToken)
.subscribe(
(user: Object) => {
this.userService.user$ = user;
this.nav.setRoot(EventListComponent);
},
(error: Object) => console.log(error)
);
I feel it is better set the user data inside the service. I could do the following:
login(accessToken: string) {
return this.http
.post('http://localhost:3000/login', {
access_token: accessToken
})
.retry(2)
.map((res: Response): any => res.json())
.subscribe(
(user: Object) => {
this.userService.user$ = user;
this.nav.setRoot(EventListComponent);
},
(error: Object) => console.log(error)
);
}
But I won't be able to subscribe to the login() function in the component since it's already subscribed. How could I redirect the user if everything ok or show an alert if anything goes wrong in the component but setting the user inside the service?
In the main component I load the user data and set the rootPage:
this.userService.loadUser().then(
(user: Object) => this.rootPage = EventListComponent,
(error: Object) => this.rootPage = LoginComponent
);
I thought that calling the loadUser() function at this time I would not have to call it again, but I have to call it in all components that I need the user data:
this.user = this.userService.user$;
this.userService.loadUser();
I don't think the service is the way it should, what could I improve? Is there any better way to achieve what I want? Any example or idea?

How to invoke component to update data?

I have a main component with 2 sub-components (update, profile).
On update component, I have a form with several input fields. When I submit a form, profile section information should update after a successful request.
The problem is, profile information doesn't update after a successful request.
So, how to invoke profile component to refresh updated data? I tried to call a service after successful request, but no luck.
By the way, parent service looks like:
#Injectable()
export class AvailabilityService {
constructor(private http: Http) {
}
getProfile() {
return this.http.get(API_URL + '/user/profile')
.map(this.extractData)
.catch(this.handleError);
}
freeOwnersParking(availableDates: AvailableDates) {
let domain = API_URL + '/parking/availability';
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
let body = JSON.stringify(availableDates);
return this.http.put(domain, body, options)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body;
}
private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
return Observable.throw(errMsg);
}
}
UPDATE
Get profile:
getProfile() {
this.availabilityService.getProfile()
.subscribe(
profile =>this.profile = profile,
error => this.errorMessage = <any>error
);
}
Update profile:
freeOwnersParking() {
this.availabilityService.freeOwnersParking(this.availableDates)
.subscribe(
response => this.availabilityService.getProfile(),
error => this.errorMessage = error
);
}
You need to leverage a shared service between them to notify the profile component.
For example an UpdateProfileService with an observable / subject in it. In this case, the profile component can subscribe on it to be notified.
Here is the service:
#Injectable()
export class UpdateProfileService {
profileUpdated:Subject<boolean> = new Subject();
(...)
updateProfile(profile:any) {
return this.http.put('http://...', profile)
.map(res => {
this.profileUpdated.next(true);
return res.json();
});
}
}
and within the profile component:
#Component({
(...)
})
export class ProfileComponent {
constructor(private service:UpdateProfileService) {
this.service.profileUpdated.subscribe(() => {
// Update bound data for profile
});
}
}

Angular2 Http / Jsonp Not Making Request

I'm using Angular 2.0.0-beta.16 and attempting to get data from my RESTful API. I have the following service:
import {Injectable} from 'angular2/core';
import {Jsonp, Response, Headers, RequestOptions} from 'angular2/http';
import {Store} from './store';
import {Observable} from 'rxjs/Observable';
import 'rxjs/Rx';
#Injectable()
export class StoreService {
constructor(private jsonp: Jsonp) {
}
getStores(): Observable<Store[]> {
console.log("getting stores");
// let headers = new Headers({ 'Content-Type': 'application/json' });
// let options = new RequestOptions({ headers: headers });
return this.jsonp.get("http://localhost:8080/stores")
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
console.log(res.status);
if (res.status < 200 || res.status >= 300) {
throw new Error('Bad response status: ' + res.status);
}
let body = res.json();
return body.data || {};
}
private handleError(error: any) {
// In a real world app, we might send the error to remote logging infrastructure
let errMsg = error.message || 'Server error';
console.error(errMsg); // log to console instead
return Observable.throw(errMsg);
}
}
From my component, I'm calling getStores(). I know it is getting into the getStores() function because I am getting the console.log message. However, nothing else happens. No request is being made that I can see in the chrome dev tools. No errors being logged to the console. Just nothing. I've tried both Jsonp and Http but they both give the same results.
You need to subscribe to the observable returned by getStores(). Observables are lazy and don't do anything without subscribe() or `toPromise()
getStores().subscribe(val => { console.log(val); };

Angular 2 - Dynamically find base url to use in the http requests (services)

I'm wondering if there is a dynamic way of getting the base url, to use in the http requests?
Is there any way of getting the http://192.123.24.2:8080 dynamically?
public getAllTickets() {
this._http.get('http://192.123.24.2:8080/services/', {
method: 'GET',
headers: new Headers([
'Accept', 'application/json',
'Content-Type', 'application/json'
])
})
So, I my request would look something like:
public getAvailableVersions() {
this._http.get('../services', {
method: 'GET',
headers: new Headers([
'Accept', 'application/json',
'Content-Type', 'application/json'
])
})
I'm looking for a way to not having to hard code the URL for the REST calls. Or is the only option to have a global variable with the URL?
Thanks!
You can create a file with your credentials
credentials.ts
export var credentials = {
client_id: 1234,
client_secret: 'secret',
host: 'http://192.123.24.2:8080'
}
And import it into your file
import {credentials} from 'credentials'
public getAllTickets() {
this._http.get(credentials.host + '/services/', {
method: 'GET',
headers: new Headers([
'Accept', 'application/json',
'Content-Type', 'application/json'
])
})
And with that you can handle dev/prod credentials
With version 2.0.0-beta.6 of Angular2, you can override the merge method
import {BaseRequestOptions, RequestOptions, RequestOptionsArgs} from 'angular2/http';
export class CustomRequestOptions extends BaseRequestOptions {
merge(options?:RequestOptionsArgs):RequestOptions {
options.url = 'http://192.123.24.2:8080' + options.url;
return super.merge(options);
}
}
You can register this class this way:
bootstrap(AppComponent, [HTTP_PROVIDERS,
provide(BaseRequestOptions, { useClass: CustomRequestOptions })
]);
Another approach could be to extend the HTTP object to add at the beginning of the request URL a base URL.
First you could create a class that extends the Http one with a baseUrl property:
#Injectable()
export class CustomHttp extends Http {
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) {
super(backend, defaultOptions);
this.baseUrl = 'http://192.123.24.2:8080';
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
console.log('request...');
return super.request(this.baseUrl + url, options).catch(res => {
// do something
});
}
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
console.log('get...');
return super.get(this.baseUrl + url, options).catch(res => {
// do something
});
}
}
and register it as described below:
bootstrap(AppComponent, [HTTP_PROVIDERS,
new Provider(Http, {
useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) => new CustomHttp(backend, defaultOptions),
deps: [XHRBackend, RequestOptions]
})
]);
you can get your application context root as below
this.baseURL = document.getElementsByTagName('base')[0].href;
import {LocationStrategy} from 'angular2/router';
constructor(private locationStrategy:LocationStrategy) {
console.log(locationStrategy.prepareExternalUrl('xxx'));
}
See also https://github.com/angular/angular/blob/1bec4f6c6135d7aaccec7492d70c36e1ceeaeefa/modules/angular2/test/router/path_location_strategy_spec.ts#L88