Reputation: 1012
I have been struggling with this now for a while and tried many solutions.
Inside my subscribe I cant access ChangeDetectorRef or the NgZone to force an update on my scope.
Why doesn't anything work? Is there any other Angular aware way of doing HTTP requests?
The login component
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, NgZone, OnInit} from '@angular/core';
import {LoginService} from './login.service';
import {Observable} from 'rxjs/Observable';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css'],
providers: [LoginService]
})
export class LoginComponent implements OnInit {
zone: NgZone;
username = '';
password = '';
showerror = false;
errormsg = '';
rs = {};
results: any;
constructor(private _loginService: LoginService, private ref: ChangeDetectorRef) {
}
refr = function () {
console.log('refresh');
console.log(this.errormsg); // is empty even after HTTP call
this.ref.markForCheck();
console.log(this.results);
};
login = function () {
console.log(this.username, this.password);
this._loginService.login(this.username, this.password).subscribe(function (data) {
console.log('log me in');
console.log(data); // the correct data is logged here
this.errormsg = 'Invalid Username and Password'; // the text is never updated
this.zone.run(); // zone has no method run
this.ref.markForCheck(); // ref has no method markForCheck
});
// this.results = this._loginService.login(this.username, this.password);
// this.results.subscribe(rs => this.rs = rs);
};
ngOnInit() {
}
}
The login service
import {Injectable} from '@angular/core';
import {CONFIG} from '../config';
import {Http, Response} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
const loginUrl: string = CONFIG.apiserv + 'api.login.php';
@Injectable()
export class LoginService {
private http;
constructor(http: Http) {
this.http = http;
}
login = function (username, password): Observable<Response> {
console.log('login clicked');
let url = new URLSearchParams();
url.append('username', username);
url.append('password', password);
const fullurl = loginUrl + '?' + url.toString();
return this.http.get(fullurl)
.map((response: Response) => response.json())
.do(data => console.log('All: ' + JSON.stringify(data)))
.catch(this.handleError);
};
handleError = function (error: Response) {
console.log(error);
return Observable.throw(error.json().error || 'Server error');
};
}
Upvotes: 1
Views: 2976
Reputation: 96939
If you want to bind this
to a newly crated scope you need to use =>
.
this._loginService.login(this.username, this.password).subscribe(data => {
See: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions
Otherwise, you could assign the this
to a variable but it's not necessary if you're using TypeScript or ES6.
var that = this;
this._loginService.login(this.username, this.password).subscribe(function (data) {
that.zone.run();
...
Upvotes: 3
Reputation: 38191
since you are using this
, you should use arrow function
:
this._loginService.login(this.username, this.password).subscribe(data => {
console.log('log me in');
console.log(data); // the correct data is logged here
this.errormsg = 'Invalid Username and Password'; // the text is never updated
this.zone.run();
this.ref.markForCheck();
});
Upvotes: 4