I am searching google all day for this problem. I understand why it is not working, but i can't find any solution or other way to get it work. I need to get it working.
I have made my own API that is correctly working when I surf to the url I get a JSON document with values. But now I got the problem with Ionic Asynchronous and Synchronous problems.
Api Service
import { Injectable } from "#angular/core";
import { HttpClient } from "#angular/common/http";
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
#Injectable()
export class ApiService {
constructor(private _http: HttpClient) { }
public getUserById(id: string)
{
return this._http.get(`mysite`);
}
profile.ts
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { ApiService} from '../../services/ApiService';
#IonicPage()
#Component({
selector: 'page-profile',
templateUrl: 'profile.html',
})
export class Profile{
user : any;
constructor(public navCtrl: NavController, public navParams: NavParams, private api : ApiService) {
}
ionViewDidLoad() {
this.api.getUserById('test').subscribe(data => {
this.user = data;
console.log(this.user);
});
console.log(this.user);
console.log('ionViewDidLoad ProfilePage');
}
}
you see two console.log(this.user), one inside the subscribe (this ons is working I see my JSON in the console). the second one outside the subscribe (this one gives a error undifined).
After searching on google I found this article that explains why it is not working. But I can't find any other solution on how to do it the correct way, because now I can't use {{user.name}} (for example) on my html.
My question is how should I work around this or how can you use API with Ionic.
Related
Following Google's official Angular 4.3.2 doc here, I was able to do a simple get request from a local json file. I wanted to practice hitting a real endpoint from JSON placeholder site, but I'm having trouble figuring out what to put in the .subscribe() operator. I made an IUser interface to capture the fields of the payload, but the line with .subscribe(data => {this.users = data}) throws the error Type 'Object' is not assignable to type 'IUser[]'. What's the proper way to handle this? Seems pretty basic but I'm a noob.
My code is below:
import { Component, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { IUsers } from './users';
#Component({
selector: 'pm-http',
templateUrl: './http.component.html',
styleUrls: ['./http.component.css']
})
export class HttpComponent implements OnInit {
productUrl = 'https://jsonplaceholder.typicode.com/users';
users: IUsers[];
constructor(private _http: HttpClient) { }
ngOnInit(): void {
this._http.get(this.productUrl).subscribe(data => {this.users = data});
}
}
You actually have a few options here, but use generics to cast it to the type you're expecting.
// Notice the Generic of IUsers[] casting the Type for resulting "data"
this.http.get<IUsers[]>(this.productUrl).subscribe(data => ...
// or in the subscribe
.subscribe((data: IUsers[]) => ...
Also I'd recommend using async pipes in your template that auto subscribe / unsubscribe, especially if you don't need any fancy logic, and you're just mapping the value.
users: Observable<IUsers[]>; // different type now
this.users = this.http.get<IUsers[]>(this.productUrl);
// template:
*ngFor="let user of users | async"
I'm on the Angular doc team and one open todo item is to change these docs to show the "best practice" way to access Http ... which is through a service.
Here is an example:
import { Injectable } from '#angular/core';
import { HttpClient, HttpErrorResponse } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import { IProduct } from './product';
#Injectable()
export class ProductService {
private _productUrl = './api/products/products.json';
constructor(private _http: HttpClient) { }
getProducts(): Observable<IProduct[]> {
return this._http.get<IProduct[]>(this._productUrl)
.do(data => console.log('All: ' + JSON.stringify(data)))
.catch(this.handleError);
}
private handleError(err: HttpErrorResponse) {
// in a real world app, we may send the server to some remote logging infrastructure
// instead of just logging it to the console
let errorMessage = '';
if (err.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
errorMessage = `An error occurred: ${err.error.message}`;
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
errorMessage = `Server returned code: ${err.status}, error message is: ${err.message}`;
}
console.error(errorMessage);
return Observable.throw(errorMessage);
}
}
The component would then look like this:
ngOnInit(): void {
this._productService.getProducts()
.subscribe(products => this.products = products,
error => this.errorMessage = <any>error);
}
I am getting the following error while using this code. I have also tried to change the push function to setRoot and the same error still persists.
I want to navigate to the home page which is the login page in case the user is not signed in but unable to do so.
The console shows that it entered the if statement but the navctrl command is not getting executed.
MyApp_Host.ngfactory.js? [sm]:1 ERROR TypeError: Cannot read property 'push' of undefined
This my code:
import { Component, ViewChild } from '#angular/core';
import { IonicPage, NavController, NavParams, AlertController} from 'ionic-angular';
import * as firebase from 'firebase/app';
import { HomePage } from '../home/home';
/**
* Generated class for the MainPage page.
*
* See https://ionicframework.com/docs/components/#navigation for more info on
* Ionic pages and navigation.
*/
#IonicPage()
#Component({
selector: 'page-main',
templateUrl: 'main.html',
})
export class MainPage {
constructor(public navParams: NavParams, public alertCtrl: AlertController, public navController:NavController) {
}
ionViewDidLoad() {
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
console.log(user);
console.log('entered in if');
// User is signed in.
} else {
console.log(user);
console.log('entered in else');
this.navController.push(HomePage);
// No user is signed in.
}
});
console.log('ionViewDidLoad MainPage')
}
}
I am using Angular http request to get a JSON response from a wordpress rest API. When I pass a parameter I do not get a response, but without the parameter it is working fine.
Here is my code from wpgetpost.service.ts file
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders} from '#angular/common/http';
import { Observable } from 'rxjs';
import { GlobalService } from '../global/global.service';
#Injectable({
providedIn: 'root'
})
export class WpgetpostService {
constructor( private http: HttpClient, private URL: GlobalService ) { }
getPost(): Observable<any[]> {
const url = this.URL.WP_API_URL;
return this.http.get<any[]>(url, {
params: {
page: '2'
},
});
}
}
Also, how can I get the headers from this response?
as per WP documentation.
using the param within the same URL.
/wp/v2/posts?page=2
I'm getting an error that FirebaseListObservable has no imported member.
Also, it's saying that import * as firebase from 'firebase/app'; is declared but not use.
what's a way I can fix this issue.
import { Injectable } from '#angular/core';
import 'rxjs/add/operator/map';
import { AngularFireAuth } from 'Angularfire2/auth';
import * as firebase from 'firebase/app';
import { AlertController } from 'ionic-angular';
import { Storage} from '#ionic/storage';
import { AngularFireDatabase, FirebaseListObservable } from 'angularfire2/database';
#Injectable()
export class UserServiceProvider {
items: FirebaseListObservable<any>;
// this will be used to find out if a user has been loggged in then nav to another page
success: boolean;
constructor(private afAuth: AngularFireAuth, public alertCtrl: AlertController,
private storage: Storage, private fbDb: AngularFireDatabase) {
// This create a refrence to the users in the database
this.items = fbDb.list('/users')
}
FirebaseListObservable is no longer used in later versions of angularfire2, try using AngularFireList instead:
import { AngularFireDatabase, AngularFireList } from 'angularfire2/database';
And then:
items: AngularFireList<any>;
If you are using firebase 4.8.1 try downgrading to 4.8.0:
npm install firebase#4.8.0
FirebaselistObservable is not used in the recent update.
Instead you need to import the following library:
import { Observable } from 'rxjs/Observable';
and declare items as:
items: Observable<firebase.User>;
Above implementation would resolve your error
I don't know what I'm doing wrong but somehow i'm not able to read data, though the data is coming from server in response and even the data is getting showed inside service extractData method when I'm putting the console but in component inside subscribe function it is giving me undefined. Help me what I'm doing wrong, what I'm assuming is that this is the problem of async but, I have no idea how correct it.
Any help will be appreciable.
Thanx in advance
Component.ts
import { Component, Input, OnInit } from '#angular/core';
import {AdminService} from './admin.service';
import {logistics} from '../shared/model/logistics';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/toPromise';
import { Observable } from 'rxjs/Observable';
import {Response } from '#angular/http';
#Component({
moduleId:module.id,
selector: 'admin',
templateUrl: 'admin.component.html',
styleUrls:['admin.component.css'],
providers:[AdminService]
})
export class AdminComponent implements OnInit{
#Input() public allocatedAssetsList: logistics[];
mode = 'Observable';
public errorMsg = '';
constructor(private adminService: AdminService) {
}
ngOnInit(){
this.listByEmpId("123");
}
listByEmpId(empId:string){
this.adminService.getAllocatedAssets(empId).subscribe(
res => this.allocatedAssetsList = res,
error => this.errorMessage = <any>error);
}
}
Service.ts
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Hero } from './hero';
import { Observable } from 'rxjs/Observable';
import { Headers, RequestOptions } from '#angular/http';
import {logistics} from '../shared/model/logistics';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class AdminService {
constructor (private http: Http) {}
private listAssetsURL = '/api/logistics/list/'; // URL to web API
private extractData(res: Response) {
let body = res.json();
return body || { };
}
private handleError (error: any) {
// In a real world app, we might use a remote logging infrastructure
// We'd also dig deeper into the error to get a better message
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg); // log to console instead
return Observable.throw(errMsg);
}
getAllocatedAssets (empId: string): Observable<logistics[]> {
this.listAssetsURL+= empId;
//let body = JSON.stringify({ empId });
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.get(this.listAssetsURL)
.map(this.extractData)
.catch(this.handleError);
}
}
listByEmpId(empId:string){
this.adminService.getAllocatedAssets(empId).subscribe(
res => {
this.allocatedAssetsList = res;
console.log(this.allocatedAssetsList);
},
error => this.errorMessage = <any>error);
}
This is probably because you are trying to access your allocatedAssetsLists before the data is actually returned from the service.
If you are accessing it in your template you can use a simple ngIf to make sure you only try to display it once the data is available.
If this is not it, we need more information on your problem to help.