Angular 2 – No data afte api call - api

I am playing around with angular 2 and the heroes tutorial. The Problem is that I always get an empty object no matter which api I call.
Here is the code:
app.compomnent.ts
import { Component, OnInit } from '#angular/core';
import { Http, Response } from '#angular/http';
// Add the RxJS Observable operators we need in this app.
import './rxjs-operators';
#Component({
selector: 'my-app',
template: `
<h1>Test</h1>
`
})
export class AppComponent implements OnInit {
constructor(private http: Http) {}
private error: any;
ngOnInit() {
var request = this.http.get('http://date.jsontest.com');
console.log("Request: " + request);
console.log("Map: " + request.map(res => res));
console.log("Complete: " + this.http.get('http://date.jsontest.com')
.map(res => res.json())
.catch(this.error));
}
}
main.ts:
// The usual bootstrapping imports
import { bootstrap } from '#angular/platform-browser-dynamic';
import { HTTP_PROVIDERS } from '#angular/http';
import { AppComponent } from './app.component';
bootstrap(AppComponent, [
HTTP_PROVIDERS
]);
The result in my console:

An Observable doesn't do anything until you subscribe to it because they are lazy
ngOnInit() {
this.http.get('http://date.jsontest.com')
.map(res => res.json())
.subscribe(
data => this.data = data,
() => console.log('done'),
err => this.error(err));
}

Related

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked in HTTP loading interceptor

Goal:
Im trying to show a loading icon on every ajax call.To this end, I added an HTTP interceptor which sets a variable to true when one or more requests are ongoing and to false when all have completed. The UI tests for this value and shows a loader or not, depending.
Problem:
On every ajax call, an error is thrown:
ExpressionChangedAfterItHasBeenCheckedError:
Expression has changed after it was checked.
Previous value: 'ngIf: [object Object]'. Current value: 'ngIf: true'.
Simplified Stakckblitz with reproducible error:
https://stackblitz.com/edit/angular-h4rpfb
Code:
appcomponent.html:
<p *ngIf="loaderService.isLoading | async">
Loading!
</p>
<p *ngIf="!(loaderService.isLoading | async)">
Not Loading!
</p>
<button (click)="loadSomething()">Load Something</button>
{{matches|async}}
appcomponent.ts:
import { Component } from "#angular/core";
import { HttpClient } from "#angular/common/http";
import { LoaderService } from "./core";
import { Observable } from "rxjs";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
matches: Observable<any>;
constructor(public loaderService: LoaderService, private http: HttpClient) {}
loadSomething() {
this.matches = this.http.get("https://jsonplaceholder.typicode.com/posts");
}
}
loader.interceptor.ts:
import { Injectable } from '#angular/core';
import {
HttpErrorResponse,
HttpResponse,
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import { LoaderService } from './loader.service';
#Injectable()
export class LoaderInterceptor implements HttpInterceptor {
private requests: HttpRequest<any>[] = [];
constructor(private loaderService: LoaderService) { }
removeRequest(req: HttpRequest<any>) {
const i = this.requests.indexOf(req);
if (i >= 0) {
this.requests.splice(i, 1);
}
console.log(i, this.requests.length);
this.loaderService.isLoading.next(this.requests.length > 0);
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.requests.push(req);
this.loaderService.isLoading.next(true);
return Observable.create(observer => {
const subscription = next.handle(req)
.subscribe(
event => {
if (event instanceof HttpResponse) {
this.removeRequest(req);
observer.next(event);
}
},
err => { this.removeRequest(req); observer.error(err); },
() => { this.removeRequest(req); observer.complete(); });
// teardown logic in case of cancelled requests
return () => {
this.removeRequest(req);
subscription.unsubscribe();
};
});
}
}
loader.service.ts:
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
#Injectable()
export class LoaderService {
public isLoading = new BehaviorSubject(false);
constructor() {}
}
Ok I got it to work by adding this to the component with the loader:
changeDetection: ChangeDetectionStrategy.OnPush
So the appcomponent.html now looks like this:
import { Component,ChangeDetectionStrategy } from "#angular/core";
import { HttpClient } from "#angular/common/http";
import { LoaderService } from "./core";
import { Observable } from "rxjs";
#Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
matches: Observable<any>;
constructor(public loaderService: LoaderService, private http: HttpClient) {}
loadSomething() {
this.matches = this.http.get("https://jsonplaceholder.typicode.com/posts");
}
}
Example:
https://stackblitz.com/edit/angular-n6fzjm

Unable to get data when making httpClient.get in angular 5

I am trying to do a http.get using httpclient. However, and i am getting
ReferenceError: data is not defined
Inside my component class when subscribing to service method.
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
const httpOptions = {
headers: new HttpHeaders()
.set('Authorization', 'Bearer xxxxx')
.set('Content-Type', 'application/json')
};
#Injectable()
export class SetsService {
constructor(private http: HttpClient) { }
getSet() {
return this.http.get('http://localhost:1234/api/users', httpOptions);
}
}
my component
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
import { Router } from '#angular/router';
import { SetsService } from '../services/sets.service';
import { Observable } from 'rxjs/Observable';
#Component({
selector: 'app-sets',
templateUrl: './sets.component.html',
styleUrls: ['./sets.component.scss']
})
export class SetsComponent implements OnInit {
id: string = "";
set: any = {};
constructor(private route: ActivatedRoute, private router: Router, private _setsService: SetsService) {
this.route.params.subscribe(res => this.id = res.id);
}
ngOnInit() {
this.getSets();
}
getSets(){
this._setsService.getSet().subscribe(
(data) => { this.set = data },
err => console.error(err),
() => { console.log('done loading set') }
);
}}
When i look at the network the API call is successful and returning data.
Inside the html I am simply trying to print the set object.

how to call api in time interval in ionic

I am working on ionic framework and i want to call API call in some time interval for ex. every 30 seconds, i want to start and stop this API call manually using button or something else. as i am new in ionic framwork i dont know how to achieve that, all i know is to call api, but i don't know how to call API in specific time interval, starting and stopping manually. so can anyone help me? thanks is advance. what i have done till now is below,
authenticate.ts
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class AuthenticateProvider {
body: any;
// apiUrl = 'https://jsonplaceholder.typicode.com';
apiUrl = 'http://dev123:5800/api';
getToken(body) {
if (this.body) {
return Promise.resolve(this.body);
}
return new Promise((resolve,reject) => {
this.http.post(this.apiUrl+'/authenticate',body)
.subscribe(res => {
resolve(res);
}, (err) => {
reject(err);
});
});
}
}
login.ts
export class LoginPage {
constructor(public navCtrl: NavController,
public authenticateProvider: AuthenticateProvider) {
}
getToken() {
this.authenticateProvider.getToken(this.creds)
.then(result => {
if (JSON.parse(result.text()).response !== "OK") {
this.err = JSON.parse(result.text()).response;
} else {
dosomething();
}
}, (err) => {
console.log("Error is" + err);
});
}
}
Create the service (I forgot its called provider these days)
ionic g provider interval
The provider code:
//interval.ts
import {Injectable} from '#angular/core';
#Injectable()
export class IntervalProvider {
intervalHandle: any = null;
constructor() {
}
toggleInterval() {
if (this.intervalHandle === null) {
this.intervalHandle = setInterval(() => {
this.callAPI();
}, 1000);
} else {
clearInterval(this.intervalHandle);
this.intervalHandle = null;
}
}
callAPI() {
console.log('API called');
}
}
Injecting and using the provider. The function toggleInterval() I am calling from a button click.
//home.ts
import { Component } from '#angular/core';
import {IntervalProvider} from '../../providers/interval/interval';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(private intervalProvider: IntervalProvider) {
}
// called by your click button
toggleInterval() {
this.intervalProvider.toggleInterval();
}
}

Creating restricted members area in Angular Fire 2

I am trying to make an application using angularfire 2. Can't find the perfect way to make the members area restricted that means only authenticated members can access that area. Here is my 'login.component.ts' file
import { Component, OnInit, HostBinding } from '#angular/core';
import { AngularFire, AuthProviders, AuthMethods } from 'angularfire2';
import { FormControl, FormGroup, Validators } from '#angular/forms';
import { Router } from '#angular/router';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css'],
})
export class LoginComponent {
state: string = '';
error: any;
login: FormGroup;
constructor(
public af: AngularFire,
private router: Router
) {
//official angfire 2 app example
//this.af.auth.subscribe(auth => console.log(auth));
}
ngOnInit() {
this.login = new FormGroup({
username: new FormControl('', Validators.required),
password: new FormControl('', Validators.required)
});
}
onSubmit() {
//console.log(this.login.value, this.login.valid);
var value = this.login.value;
//console.log(value.username);
//console.log(value.password);
this.af.auth.login({
email: value.username,
password: value.password,
},
{
provider: AuthProviders.Password,
method: AuthMethods.Password,
}).then(
(success) => {
console.log(success);
this.router.navigate(['/members']);
}).catch(
(err) => {
console.log(err);
this.error = err;
})
}
}
and the members.component.ts file
import { Component, OnInit } from '#angular/core';
import { AngularFire, AuthProviders, AuthMethods } from 'angularfire2';
import { Router } from '#angular/router';
#Component({
selector: 'app-other',
templateUrl: './members.component.html',
styleUrls: ['./members.component.css']
})
export class MembersComponent implements OnInit {
//name: "";
//state: string = '';
constructor(
public af: AngularFire,
private router: Router
) {
this.af.auth.subscribe(auth => {
if(auth) {
console.log(auth);
}
});
}
logout() {
this.af.auth.logout();
console.log('logged out');
this.router.navigate(['/login']);
}
ngOnInit() {
}
}
I know my code may be seem like a dumb one but actually I am trying to study over this. But there is not enough documentation to solve my problem I guess. Thanks in advance.
https://coursetro.com/posts/code/32/Create-a-Full-Angular-Authentication-System-with-Firebase
this is a great tutorial that solves your problem

How to use extends for this angulr2 scenario?

In my application core component is root component, In this page header , sidemenu designs are existed,
SideMenu is dynamic, so I write logic of the code in other sidemenu component,
Now I want to use the functionality of sidemenu in core component, I think it is
done by using extends,
My componets are
core component
import { Component, OnInit } from '#angular/core';
import {SidemenuComponent} from './sidemenu.component';
#Component({
selector: 'my-admin',
templateUrl: '../views/admin-header.html'
})
export class CoreComponent extends SidemenuComponent {
constructor( private router: Router) {
}
}
sidemenucomponent
import {OnInit } from '#angular/core';
import { Http, Response, Headers, RequestOptions } from '#angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/toPromise';
import {MenuService} from './core.service';
export class SidemenuComponent implements OnInit{
userroleId : any;
roleName: string;
menuItems:any;
constructor(private http: Http,private MenuService:MenuService) {
this.userroleId = localStorage.getItem("roleId")
}
ngOnInit(): void {
this.getSideMenu();
}
getSideMenu () {
if( this.userroleId == 1) {
this.MenuService.getAdminMenu().subscribe(menuItems => this.menuItems= menuItems, error => console.log(error));
}
if(this.userroleId == 2){
this.MenuService.getpractitionerMenu().subscribe(menuItems => this.menuItems= menuItems, error => console.log(error));
console.log('ss')
}
}
}
MenuService
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class MenuService {
constructor(private http: Http) {}
public getAdminMenu(): Observable<any> {
return this.http.get("./app/core/adminsidemenu.json")
.map((res:any) => res.json())
.catch(this.handleError);
}
public getpractitionerMenu(): Observable<any> {
return this.http.get("./app/core/practitioner.json")
.map((res:any) => res.json())
.catch(this.handleError);
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error); // for demo purposes only
return Promise.reject(error.message || error);
}
}
Here I am unable extends the sidemenu component in core component.
I am getting error in my console:
Constructors for derived classes must contain a 'super' call.
Please help me
It appears you may be missing the #Component decorator on the SidemenuComponent.
Here's a Plunker with a simple extended Component, and here's a good article on it: Component Ineritance.
You need to call the constructor of the parent class in your child-class:
#Component({
selector: 'my-admin',
templateUrl: '../views/admin-header.html'
})
export class CoreComponent extends SidemenuComponent {
constructor( private router: Router, http: Http, menuService:MenuService) {
super(http,menuService);
}
}