For a JWT authentification, I make a post request to get the token using the new Http
module working with Observables now.
I have a simple Login
component showing the form:
@Component({
selector: 'my-login',
template: `<form (submit)="submitForm($event)">
<input [(ngModel)]="cred.username" type="text" required autofocus>
<input [(ngModel)]="cred.password" type="password" required>
<button type="submit">Connexion</button>
</form>`
})
export class LoginComponent {
private cred: CredentialsModel = new CredentialsModel();
constructor(public auth: Auth) {}
submitForm(e: MouseEvent) {
e.preventDefault();
this.auth.authentificate(this.cred);
}
}
I have a Auth
service making the request:
@Injectable()
export class Auth {
constructor(public http: Http) {}
public authentificate(credentials: CredentialsModel) {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers})
.map(res => res.json())
.subscribe(
data => this._saveJwt(data.id_token),
err => console.log(err)
);
}
}
Works well but now I want to display error messages inside my component so I need to subscribe in 2 places (Auth
for managing success and Login
for managing error).
I achieved it using share
operator:
public authentificate(credentials: CredentialsModel) : Observable<Response> {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
const auth$ = this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers})
.map(res => res.json()).share();
auth$.subscribe(data => this._saveJwt(data.id_token), () => {});
return auth$;
}
And inside the component:
submitForm(e: MouseEvent) {
e.preventDefault();
this.auth.authentificate(this.cred).subscribe(() => {}, (err) => {
console.log('ERROR component', err);
});
}
It works but I feel doing it wrong..
I just transpose the way we did it with angular1 and promises
, do you see better way to achieve it?
Subscribinglink An Observable instance begins publishing values only when someone subscribes to it. You subscribe by calling the subscribe() method of the instance, passing an observer object to receive the notifications.
Executing an Observable But the observable function does not emit any values until it is executed. The subscribe() method calls the observable's function that produces and emits data. Thus, subscribing to an observable starts a flow of data between the observable and the observer.
Normally Subscription means an arrangement to receive something. Similarly, in Angular applications Observables will be connected to observers and whenever they observe a new value or change in data, they will execute code with the help of Subscription and all the subscribed components will receive the updated outcome.
You don't need to unsubscribe from observable created by Http or HttpClient because it is finite observable (value will be emitted only once and complete will be called). However, you CAN unsubscribe from the observable created by HttpClient to cancel the request.
Why would you subscribe to in sharedService
, when this approach can be used !
@Injectable()
export class Auth {
constructor(public http: Http) {}
public authentificate(credentials: CredentialsModel) {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers}) //added return
.map(res => res.json());
//.subscribe(
// data => this._saveJwt(data.id_token),
// err => console.log(err)
//);
}
}
@Component({
selector: 'my-login',
template: `<form (submit)="submitForm($event)">
<input [(ngModel)]="cred.username" type="text" required autofocus>
<input [(ngModel)]="cred.password" type="password" required>
<button type="submit">Connexion</button>
</form>`
})
export class LoginComponent {
private cred: CredentialsModel = new CredentialsModel();
constructor(public auth: Auth) {}
submitForm(e: MouseEvent) {
e.preventDefault();
this.auth.authentificate(this.cred).subscribe(
(data) => {this.auth._saveJwt(data.id_token)}, //changed
(err)=>console.log(err),
()=>console.log("Done")
);
}
}
sharedService
and component
you can surely go with this approach. But I'd not recommend this rather before edited section seems perfect to me.
I can't test it with your code. but look at my example here(tested). click on myFriends tab
,check browser console and UI. browser console shows subscription result of sharedService
& UI shows subscription result of component
.
@Injectable()
export class Auth {
constructor(public http: Http) {}
public authentificate(credentials: CredentialsModel) {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
var sub = this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers}) //added return
.map(res => res.json());
sub.subscribe(
data => this._saveJwt(data.id_token),
err => console.log(err)
);
return sub;
}
}
export class LoginComponent {
private cred: CredentialsModel = new CredentialsModel();
constructor(public auth: Auth) {}
submitForm(e: MouseEvent) {
e.preventDefault();
this.auth.authentificate(this.cred).subscribe(
(data) => {this.auth._saveJwt(data.id_token)}, //not necessary to call _saveJwt from here now.
(err)=>console.log(err),
()=>console.log("Done")
);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With