Undefined Data When Calling From JSON in Ionic 2 - angularjs

I have a firebase URL to get some test data from as I'm still learning Ionic 2. Originally I had the error 'No HTTP Provider', but I fixed that by adding HttpModule to the app.module.ts file, but since that my data is always coming back as undefined.
The service is in it's own file (ww-api.service.ts):
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
#Injectable()
export class WildWalkApi {
private baseUrl = 'https://i2test-ea07c.firebaseio.com/';
constructor(private http: Http) {}
getLoginTest(){
return new Promise(resolve => {
this.http.get(this.baseUrl + 'login.json')
.subscribe(res => resolve(res.json()));
});
}
}
Then this is exported using a shared file (shared.ts):
export * from './ww-api.service';
This then goes into app.componant.ts:
import { WildWalkApi } from './shared/shared';
#Component({
templateUrl: 'app.html',
providers: [
WildWalkApi,
HttpModule
]
})
And finally I try and use the data in my view:
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { WildWalkApi } from "../../app/shared/shared";
#IonicPage()
#Component({
selector: 'page-home-logged-in',
templateUrl: 'home-logged-in.html',
})
export class HomeLoggedIn {
private login;
constructor(public navCtrl: NavController, public navParams: NavParams, private wwapi: WildWalkApi) {
}
ionViewDidLoad() {
this.wwapi.getLoginTest().then(data => this.login = data);
console.log('ionViewDidLoad HomeLoggedIn ' + this.login);
}
}
However this.login is always coming back as undefined.

In your code You're trying to print the value right after sending the request but data is not available at that time .
You can use Event for it . Refer http://ionicframework.com/docs/api/util/Events/
sample is here
In that file from where you want to use that event is
this.events.publish('user:loggedIn', data);
and that file where you want to show that data is
this.events.subscribe('user:loggedIn', (data) => {
console.log("page 1 data "+data);
this.page1Message=data;
});
This may work for you .

Related

Passing an array between pages in ionic 2

I'm new in Ionic 2 and I'm having troubles with passing data between pages. In my Home.ts file I have a global array that contains some numbers I calculated and i want to pass it to my Table.ts file, to show it in a HTML table with the *ngFor method.
this is the Function in Home.ts where i fill the array and try to push (i will skip the calculations, becacause i know they are correct).
`import { Component } from '#angular/core';
import { AlertController } from 'ionic-angular';
import { IonicPage,NavController, NavParams} from 'ionic-angular';
import {Table} from '../table/table';
export class HomePage {
averagesList: Array <number> =[];
constructor(public alerCtrl: AlertController,
public navCtrl: NavController,
public navParams: NavParams)
{}
Calculate(){
var Averages=[];
//Calculations on the 'Averages' Array
this.averagesList = Averages;
this.navCtrl.push(Table,this.averagesList);
}
}
So I try to print it in my Table.ts file but it gives me undefined result
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import {HomePage} from '../home/home';
#IonicPage()
#Component({
selector: 'page-table',
templateUrl: 'table.html',
})
export class Table{
constructor(public navCtrl: NavController, public navParams: NavParams) {
}
ionViewDidLoad() {
console.log(this.navParams.get('averagesList'));
}
}
I've tried to pass a let variable and it worked, so why doesn't it work with arrays?
Your mistake is using console.log(this.navParams.get('averagesList'));
Here 'averagesList' is the key.
To get it this way, you need to send as :
this.navCtrl.push(Table,{'averagesList' : this.averagesList});
Else:
if you directly send as
this.navCtrl.push(Table,this.averagesList);
You can retrieve value like so:
console.log(this.navParams.data);
you can use services to do so. Just like in angular2 you can import your service within the constructor and use the property like this.
import {OnInit} from '#angular/core';
import {someService} from ./somepath;
...
export class someClass implements OnInit{
let myTmpVar; //we will capture the shared data in this variable
constructor (private smService: someService){ ... }
ngOnInit{
this.myTmpVar = this.smService.SharedServiceData;
}
...
}
It's better to use service for passing nested data. In your case calculations object.
You can create messageService and listen to changes, something like below.
import {Injectable} from '#angular/core';
import {Observable} from 'rxjs';
import {Subject} from 'rxjs/Subject';
#Injectable()
export class LocalMsgService {
private subject = new Subject();
sendMessage(message) {
this.subject.next(message);
}
clearMessage() {
this.subject.next();
}
getMessage(): Observable<any> {
return this.subject.asObservable();
}
}
Which can be used in your home.ts and table.ts pages as follows
Home.ts
//other imports comes here
import {LocalMsgService} from 'services/localMsg';
#Component({
selector: 'home-component',
templateUrl: 'home.html'
})
export class HomePage {
constructor( private msgService: LocalMsgService) {
}
dataToPass() {
console.log(this.averagesList);
this.msgService.sendMessage(this.averagesList);
}
}
Table.ts
//other imports comes here
import {LocalMsgService} from 'services/localMsg';
import {Subscription} from 'rxjs/Subscription';
#Component({
selector: 'page-table',
templateUrl: 'table.html',
})
export class TablePage{
items: any;
subscription: Subscription;
constructor(
public localMsgService : LocalMsgService) {
this.subscription = this.localMsgService.getMessage().subscribe(msg => {
this.items = msg;
});
}
}

get json data from service to page in ionic 3

I'm trying to load a JSON from remote server which I already obtained in a service using http.get(), but I can't get the data from my service into my page. I can see the json data is loaded in the service in console.log but can't find a way to get it into my page so I can use those data in my UI. Does anybody see what i'm doing wrong here?
here is the code of my service
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/timeout';
#Injectable()
export class MyService {
returnedData;
constructor(public http: Http) {
console.log('Hello MyService Provider');
}
getRemoteData(){
console.log('Hello inside getRemoteData');
this.http.get('https://randomuser.me/api/?inc=gender,name,email,phone,picture,location').map(res => res.json()).subscribe(data => {
console.log(data);
this.returnedData=data;
});
return returnedData;
}
}
here is my page
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { MyService } from '../../providers/my-service';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
myJson;
constructor(public navCtrl: NavController, public serviceOne: MyService) {
}
ionViewDidload(){
console.log('Hello MyService called');
this.myJson=this.serviceOne.getRemoteData;
console.log('myJson');
}
getRandomSpan(){
return Math.floor((Math.random()*10)+1);
};
}
I want to get the value of the json I received from server into myJson variable.
so I can use those data into UI.

HTTP PUT Request Returns Empty From Angular 2 Service

I'm calling data from a service. I have to pass in an object with properties to retrieve the data. From what I can tell, I'm passing it in correctly and not receiving any errors in console, but the object that I assign to the data is empty. I'm including my Service and Component where I'm outputting the data.
I call the exact same endpoint from an Angular1 App with the same "payload" values and get my data object returned. I'm sure I'm missing something simple. Still getting used to Angular 2.
SERVICE
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
#Injectable ()
export class DataService {
private qrDataUrl = 'http://my.data.url/endpoint';
private payload = {
DeliveryTypeId: 0,
PickupLocationid: 0,
PaymentTypeId: 0,
Items: ['XXXX'],
ApplicationToken:'123MYTOKEN456',
DateOfBirth: "1961-01-01T00:00:00.000Z"
};
constructor(private http: Http){ }
getQr():Observable<any>{
return this.http.put(this.qrDataUrl, this.payload)
.map((res:Response) => res.json());
}
}
COMPONENT
import { Component, OnInit } from '#angular/core';
import { DataService } from '../shared/dataService';
#Component({
selector: 'my-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss'],
providers: [DataService]
})
export class HomeComponent implements OnInit {
qrData = { };
constructor(private dataService: DataService) {
// Do stuff
}
getData(){
this.dataService.getQr().subscribe(data => this.qrData = data);
console.log(this.qrData); //This logs an empty object
}
ngOnInit() {
console.log('Hello Home');
this.getData();
}
}
Asynchronous operation doesn't work synchronous way. You have to wait until the ajax gets completed. You can only see a data inside subscription of your getQr function once the service call resolved.
getData(){
this.dataService.getQr().subscribe(data => {
this.qrData = data;
console.log(this.qrData); //This logs an empty object
});
}

Can't inject service in component in Ionic 2

I have a simple ionic 2 app.
Created at service
import { Storage } from '#ionic/storage';
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import { AlertController } from 'ionic-angular';
import { NavController, NavParams } from 'ionic-angular';
import { AgendaPage } from '../pages/agenda/agenda';
import { LoginPage } from '../pages/login/login';
import 'rxjs/add/operator/map';
#Injectable()
export class Auth {
constructor(public http: Http, public storage: Storage, public alertCtrl: AlertController, public navCtrl: NavController) {}
}
app.components.ts registration
import { Component, ViewChild } from '#angular/core';
import { Nav, Platform } from 'ionic-angular';
import { StatusBar, Splashscreen } from 'ionic-native';
import { Auth } from '../providers/auth';
import { Rides } from '../providers/rides';
import { AgendaPage } from '../pages/agenda/agenda';
import { LoginPage } from '../pages/login/login';
#Component({
templateUrl: 'app.html',
providers: [Auth, Rides]
})
export class MyApp {
#ViewChild(Nav) nav: Nav;
rootPage: any = LoginPage;
pages: Array<{title: string, component: any}>;
constructor(public platform: Platform) {
this.initializeApp();
// used for an example of ngFor and navigation
this.pages = [
{ title: 'Minha Agenda', component: AgendaPage }
];
}
initializeApp() {
this.platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
StatusBar.styleDefault();
Splashscreen.hide();
});
}
openPage(page) {
// Reset the content nav to have just this page
// we wouldn't want the back button to show in this scenario
this.nav.setRoot(page.component);
}
}
Trying to inject it into a component
import { Component } from '#angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { Auth } from '../../providers/auth';
/*
Generated class for the Agenda page.
See http://ionicframework.com/docs/v2/components/#navigation for more info on
Ionic pages and navigation.
*/
#Component({
selector: 'page-agenda',
templateUrl: 'agenda.html',
providers: [Auth]
})
export class AgendaPage {
openRides: any;
constructor(public navCtrl: NavController, public navParams: NavParams, private auth: Auth) {}
}
I get the following error:
Can't resolve all parameters for AgendaPage: (NavController,
NavParams, ?).
What I find strange is that I have a very similar other component where I can user the service without problems:
import { Component } from '#angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { Auth } from '../../providers/auth';
/*
Generated class for the Login page.
See http://ionicframework.com/docs/v2/components/#navigation for more info on
Ionic pages and navigation.
*/
#Component({
selector: 'page-login',
templateUrl: 'login.html',
providers: [Auth]
})
export class LoginPage {
email: string;
password: string;
constructor(public navCtrl: NavController, public navParams: NavParams, private auth: Auth) {}
login() {
}
}
This works perfectly.
If it's an authentication service, you probably don't need to provide it at the lower levels of abstraction. It still needs to be imported to be used, but it doesn't need to be added to the providers[] in your lower tier components.
This may be causing the error, as for some reason it might not be able to provide an instance of Auth at that level of abstraction for whatever reason. Notably, I try not to use constructors on my services -- that may be causing the issue as well (or both issues together.)
The problem here is circular dependency. You are already importing the component in your service and want to inject the service in the same component. So angular does not know which to load first.
You need to look into forwardref.
In your component constructor,
constructor(...,#Inject(forwardref(()=>Auth))auth)
You might want to refer here for more.

Trying to execute component function after auth.login() with Facebook Auth0 Angular 2

I'm trying to execute a component function after Auth0 logs someone in via Facebook authentication. I'm trying to have that component function send a POST request with the Facebook profile object (along with another property I add in) to the ExpressJS server, which then saves it to MongoDB. The problem is, I haven't been able to get it to work. I'm wondering if I could modify the auth.login() function to instead return a promise, and take in a the extra parameter I need, and then subscribe to that from my component, and on success send the object. I've also tried to just put the POST request itself in the Auth Service constructor, but that hasn't worked. Here is my code so far:
home.html
...
<button class="btn btn-primary pull-left" type="submit" (click)="someFunction('extraProperty')">Submit</button>
...
home.component.ts
import { Component } from '#angular/core';
import { HomeService } from './home.service';
import { Auth } from './auth.service';
#Component({
moduleId: module.id,
selector: 'my-home',
templateUrl: 'home.html',
})
export class HomeComponent {
constructor(private homeService: HomeService, private auth: Auth) { }
someFunction(extraProperty: string): void {
// Saving extraProperty to local storage, then authenticating
localStorage.setItem('extraProperty', extraProperty);
this.auth.login();
}
}
home.service.ts
import { Injectable } from '#angular/core';
import {Observable} from 'rxjs/Rx';
import { Http, Response, Headers, RequestOptions } from '#angular/http';
import { Auth } from './auth.service';
#Injectable()
export class HomeService {
constructor (private http: Http) {}
private serverUrl = 'http://localhost:8000/';
// Trying to call this function after Auth Service login
postVote(body: Object): Observable<Boolean[]> {
return this.http.post((this.serverUrl + 'postVote'), body)
.map((res:Response) => {
console.log("Res is: ", res);
})
.catch((error:any) => Observable.throw(error.json().error || 'Server error'));
}
}
auth.service.ts
import { Injectable } from '#angular/core';
import { tokenNotExpired } from 'angular2-jwt';
import { HomeService } from './home.service';
import { Http, Response, Headers, RequestOptions } from '#angular/http';
import {Observable} from 'rxjs/Rx';
// Avoid name not found warnings
declare var Auth0Lock: any;
#Injectable()
export class Auth {
// Configure Auth0
lock = new Auth0Lock('CLIENT_ID', 'DOMAIN');
userProfile: any;
constructor(private homeService: HomeService, private http: Http) {
// Set userProfile attribute of already saved profile
this.userProfile = JSON.parse(localStorage.getItem('profile'));
// Add callback for lock `authenticated` event
this.lock.on("authenticated", (authResult) => {
localStorage.setItem('id_token', authResult.idToken);
// Fetch profile information
this.lock.getProfile(authResult.idToken, (error, profile) => {
if (error) {
// Handle error
alert(error);
return;
}
profile.extraProperty = localStorage.getItem('extraProperty');
localStorage.setItem('profile', JSON.stringify(profile));
this.userProfile = profile;
console.log(profile);
// Tried calling the service here, but I don't think it would work anyways in the constructor.
this.homeService.postVote(this.userProfile);
});
});
}
public login() {
// Call the show method to display the widget.
this.lock.show();
};
...
}
If I could also go about this in any other way that would be easier that you know of, that would be helpful as well. Essentially I'm trying to get the user's profile, save it to a DB in order to match them up with one person that holds the corresponding extraProperty, redirect to a new module and render the profile pic and name of the person with their match.
Thanks in advance!
Edit: Here is the function postVote on the server side. Hope that helps
// Adding vote object to MongoDB
router.post('/postVote', function(req, res, next) {
console.log("Req.body is: ", req.body);
Vote.save(function(err) {
if(err) {
throw err;
// return err;
}
console.log("Vote saved");
});
res.sendStatus(200);
});

Resources