Explanation of Observable Post
setupponent.ts
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Post } from './model/post';
import { PostService } from './service/post.service';
@Component({
selector: 'setup',
templateUrl: './setupponent.html',
styleUrls: ['./setupponent.scss']
})
export class SetupComponent implements OnInit {
@Output()
change: EventEmitter<string> = new EventEmitter();
postUsers(input){
this.postService.postUser(input)
.subscribe(
post => {
this.post = post
},
err => {
console.log(err);
});
}
clicked(value) {
console.log(value);
this.postUsers(this.input)
// this.change.emit(value);
}
plexForm : FormGroup;
constructor(private postService: PostService) {}
post: Post[];
ngOnInit() {}
}
post.service.ts
import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { Post } from '../model/post';
import { Observable } from 'rxjs/Rx';
// Import RxJs required methods
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
@Injectable()
export class PostService {
constructor (private http: Http) {}
private registerUrl = 'http://localhost:2001/api/users/register';
postUser(user:Post) : Observable<Post[]>{
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(this.registerUrl, user, options)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body || { };
}
private handleError (error: Response | any) {
// In a real world app, you 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);
}
}
model/post.ts
export class Post {
constructor(
public id: number,
public name: string,
public email: string,
public password: string
){}
}
I understand what the model/post.ts does, it defines the property types, what I need is clarification on the subscribe method within setupponents.ts
. The Observable gets invoked inside clicked()
but what I want to understand is how does this because accessible to the application so that I can proceed after the action has run its course this.postUsers(this.input)
Typically with a Promise I would have done the following
this.postUsers(this.input)
.then(function(){
});
I'd really like it if someone could explain how it works and how to achieve a confirmation that the post has pleted to then run the next function
ie I have this
clicked(value) {
console.log(value);
this.postUsers(this.input)
// this.change.emit(value);
}
but in promise I'd do
clicked(value) {
console.log(value);
this.postUsers(this.input)
.then(function(){
this.change.emit(value);
});
}
How can I get this to work with Observables? I tried to see what was returned by doing
clicked(value) {
console.log(value);
const runThis = this.postUsers(this.input);
console.log(runThis);
// this.change.emit(value);
}
but it returns undefined
.
Explanation of Observable Post
setup.ponent.ts
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Post } from './model/post';
import { PostService } from './service/post.service';
@Component({
selector: 'setup',
templateUrl: './setup.ponent.html',
styleUrls: ['./setup.ponent.scss']
})
export class SetupComponent implements OnInit {
@Output()
change: EventEmitter<string> = new EventEmitter();
postUsers(input){
this.postService.postUser(input)
.subscribe(
post => {
this.post = post
},
err => {
console.log(err);
});
}
clicked(value) {
console.log(value);
this.postUsers(this.input)
// this.change.emit(value);
}
plexForm : FormGroup;
constructor(private postService: PostService) {}
post: Post[];
ngOnInit() {}
}
post.service.ts
import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { Post } from '../model/post';
import { Observable } from 'rxjs/Rx';
// Import RxJs required methods
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
@Injectable()
export class PostService {
constructor (private http: Http) {}
private registerUrl = 'http://localhost:2001/api/users/register';
postUser(user:Post) : Observable<Post[]>{
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(this.registerUrl, user, options)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body || { };
}
private handleError (error: Response | any) {
// In a real world app, you 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);
}
}
model/post.ts
export class Post {
constructor(
public id: number,
public name: string,
public email: string,
public password: string
){}
}
I understand what the model/post.ts does, it defines the property types, what I need is clarification on the subscribe method within setup.ponents.ts
. The Observable gets invoked inside clicked()
but what I want to understand is how does this because accessible to the application so that I can proceed after the action has run its course this.postUsers(this.input)
Typically with a Promise I would have done the following
this.postUsers(this.input)
.then(function(){
});
I'd really like it if someone could explain how it works and how to achieve a confirmation that the post has pleted to then run the next function
ie I have this
clicked(value) {
console.log(value);
this.postUsers(this.input)
// this.change.emit(value);
}
but in promise I'd do
clicked(value) {
console.log(value);
this.postUsers(this.input)
.then(function(){
this.change.emit(value);
});
}
How can I get this to work with Observables? I tried to see what was returned by doing
clicked(value) {
console.log(value);
const runThis = this.postUsers(this.input);
console.log(runThis);
// this.change.emit(value);
}
but it returns undefined
.
Similar with promises make your postUsers
method return an observable (not a subscription)
postUsers(input){
return this.postService.postUser(input);
}
Then you can subscribe to this method like using a then
in promises.
clicked(value) {
console.log(value);
this.postUsers(this.input).subscribe((response)=> {
this.change.emit(value);
});
}
You can also convert observables into promises. Then you wouldn't get confused.
import 'rxjs/add/operator/toPromise';
postUsers(input){
return this.postService.postUser(input).toPromise();
}
clicked(value) {
console.log(value);
this.postUsers(this.input)
.then((res)=>{
this.change.emit(value);
});
}
Note that I haven't used the function
keyword in my callbacks. If I did this.change
would refer to the callbacks change
because the this
wouldn't refer to the ponent.
how to achieve a confirmation that the post has pleted
When the stream triggers plete
callback you will know the request has pleted. This is the third callback you pass to the subscribe method or the plete
method if you pass observer object instead of callbacks.
I think you will benefit from knowing how the operator toPromise
work. You can then use it directly or emulate its logic. You can use it:
this.postUsers(this.input).toPromise()
.then(function(){
...
});
Basically what it does is creates a promise and returns it. Then it subscribes the the observable returned by the this.postUsers
and waits until this observable emits pleted
event. After that, it resolves the promise with the last event it returned. Something along these lines:
toPromise(observable) {
let lastReturnedValue = null;
return new Promise() {
observable.subscribe(
(v)=>{
lastReturnedValue = v;
},
(e)=>{
reject(e);
},
(c)=>{
resolve(lastReturnedValue);
});
}
}
So just as with toPromise
you can subscribe to the observable and listen for plete
event:
clicked(value) {
console.log(value);
this.postUsers(this.input).subscribe(
(v)=>{ // here you get the value and can save it },
(e)=>{ // here you know that observable has error, similar to `catch` callback },
()=>{ // here you know that observable has pleted, similar to `then` callback}
);
console.log(runThis);
// this.change.emit(value);
}
Or you can return the observable for someone else to listen:
clicked(value) {
return this.postUsers(this.input)
}
...
clicked().subscribe( // all the code from previous example)