how to call api in time interval in ionic - api

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();
}
}

Related

Oazapfts.fetchJson is not define while in Jest test

I'm trying to create test for call api fn but i get - oazapfts.fetchJson is not define while runing the test.
the prject is in vue3 with quasar, oazapftp and Jest.
So my component looks like this:
import { putAdduser } from '../components/models'
import { handle } from 'oazapfts'
import { useRouter } from 'vue-router'
import { Notify } from 'quasar'
async function createUser() {
//if pass is ok ten:
await handle(putAdduser({ name: name.value, pass: password.value }), {
201(data) {
Notify.create({
message: data.message,
color: 'green-10',
})
router.push('/login')
},
409(message) {
Notify.create(message)
},
500(message) {
Notify.create(message)
},
})
return 'hello'
}
the api handler is :
export function putAdduser(user?: User, opts?: Oazapfts.RequestOpts) {
return oazapfts.fetchJson<{
status: 201;
data: Message;
} | {
status: 409;
data: Message;
} | {
status: 500;
data: Message;
}>("/dosome", oazapfts.json({
...opts,
method: "PUT",
body: user
}));
}
i've tried:
import { describe, expect, it } from '#jest/globals'
import { installQuasarPlugin } from '#quasar/quasar-app-extension-testing-unit-jest'
import { mount } from '#vue/test-utils'
import { Notify } from 'quasar'
import myComp from '../../../src/components/myComp'
installQuasarPlugin({ plugins: { Notify } })
const wrapper = mount(myComp)
const { vm } = wrapper
it('add User', async () => {
const res = await vm.createUser()
expect(res).toBe('hello')
})
My problem is how to let Jest use this call.

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

Angular 5 auth get token

I am working on Angular5 app user authentication, api return token on successful login. For some reasons LoginPageComponent has no idea what is the token, even if I store it in localstorage I will still get null.
What to do?
App Structure:
LoginPageComponent
import { Component, ViewChild } from '#angular/core';
import { NgForm } from '#angular/forms';
import { Router, ActivatedRoute } from "#angular/router";
import { AuthService } from '../../../shared/auth/auth.service';
#Component({
selector: 'app-login-page',
templateUrl: './login-page.component.html',
styleUrls: ['./login-page.component.scss']
})
export class LoginPageComponent {
#ViewChild('f') loginForm: NgForm;
private user: any = {
email: '',
password: ''
};
constructor(
private auth: AuthService,
private router: Router,
private route: ActivatedRoute) { }
// On submit button click
onSubmit(f: NgForm) {
this.auth.signinUser(f.value.email, f.value.password);
// Returns even signinUser has token
console.log(this.auth.getToken());
}
}
AuthService
signinUser(email: string, password: string) {
this.userService.login(email, password).then(res => {
console.log(res);
this.token = res.token;
// here app has token and this.token contains value
});
}
getToken() {
return this.token;
}
UserService:
login(email, password) {
this.endpoint = this.endpointLocal + '/api/auth/login';
return new Promise(resolve => {
this.http.post(this.endpoint, {"email": email, "password": password})
.subscribe(res => resolve(res.json()));
});
}
Your call to signinUser invokes asynchronous code, so the then portion of the Promise in signinUser won't have been executed before you make your console.log call in onSubmit.
If you modify your signinUser method in the AuthService to return the Promise, then you can just chain a .then call in your LoginPageComponent.onSubmit method:
signinUser(email: string, password: string): Promise {
return this.userService.login(email, password).then(res => {
console.log(res);
this.token = res.token;
// here app has token and this.token contains value
});
}
// On submit button click
onSubmit(f: NgForm) {
this.auth.signinUser(f.value.email, f.value.password).then(() => {
console.log(this.auth.getToken());
});
}

Ionic Firebase Google Login

I'm new at App Developing, but I am building an app with a Google Login connected to my Firebase.
I can connect and show the user id with success but I want to go to another page (HomePage) when success login.
import { HomePage } from "../home/home";
import { RegisterPage } from "../register/register";
import * as firebase from "firebase/app";
import { AngularFireAuth } from "angularfire2/auth";
import { Observable } from "rxjs/Observable";
import { Router } from "#angular/router";
import { GooglePlus } from "#ionic-native/google-plus";
import { Platform } from "ionic-angular";
#IonicPage()
#Component({
selector: "page-login",
templateUrl: "login.html"
})
export class LoginPage {
user: Observable<firebase.User>;
constructor(
public nav: NavController,
public navParams: NavParams,
public forgotCtrl: AlertController,
public menu: MenuController,
public toastCtrl: ToastController,
private afAuth: AngularFireAuth,
private gplus: GooglePlus,
private router: Router,
private platform: Platform
) {
this.menu.swipeEnable(false);
this.user = this.afAuth.authState;
}
async nativeGoogleLogin(): Promise<void> {
try {
const gplusUser = await this.gplus.login({
webClientId:
"MyClientWebAPI",
offline: true,
scopes: "profile email"
});
return await this.afAuth.auth.signInWithCredential(
firebase.auth.GoogleAuthProvider.credential(gplusUser.idToken)
//Here is where i try to inject the router.
.then(success => {
this.router.navigate(["HomePage"]);
})
);
} catch (err) {
console.log(err);
}
}
googleLogin() {
if (this.platform.is("cordova")) {
this.nativeGoogleLogin();
} else {
this.webGoogleLogin();
}
}
I tried to inject some code in the auth by using then(success =>....) but I can't get it to work.
Can anyone help with the code?
Thanks
return await this.afAuth.auth
.signInWithCredential(
firebase.auth.GoogleAuthProvider.credential(gplusUser.idToken)
)
.then(data => {
this.nav.setRoot(HomePage);
});
} catch (err) {
console.log(err);
}
}
async webGoogleLogin(): Promise<void> {
try {
const provider = new firebase.auth.GoogleAuthProvider();
const credential = await this.afAuth.auth
.signInWithPopup(provider)
.then(data => {
this.nav.setRoot(HomePage);
});
} catch (err) {
console.log(err);
} }
Maybe you can do this:
async loginUser() {
this.user.email = this.myForm.value.email;
this.user.password = this.myForm.value.password;
this.presentLoading();
try {
this.authService
.signInWithEmailAndPassword(this.user)
.then(data => {
this.navCtrl.setRoot(ListaPage);
})
.catch(e => {
console.log("error");
});
} catch (e) {
console.error(e);
}
}
and in AuthService you can insert the Google Login Logic.

The requested path contains undefined segment at index 0

authentication.service.ts in that my login service is define like this
import { Injectable } from '#angular/core';
import { Http, Headers, Response, RequestOptions } from '#angular/http';
import { Observable } from 'rxjs';
import 'rxjs/Rx';
import 'rxjs/add/operator/map'
import { AuthHttp } from 'angular2-jwt';
import { Router } from '#angular/router';
#Injectable()
export class AuthenticationService {
token: string;
redirectUrl: any;
constructor(public router: Router, private http: Http, private authHttp: AuthHttp) {
//set token if saved in local storage
if (localStorage.getItem('authToken') != null) {
try {
// var currentUser =
JSON.parse(localStorage.getItem('currentUser'));
this.token = localStorage.getItem('authToken');
// this.token = currentUser && currentUser.token;
} catch (e) {
localStorage.removeItem("authToken");
}
}
}
login(username: string, password: string) {
return this.http.post('http://localhost:3002/api/authenticate',({ username: username, password: password }))
.map(res => {
console.log(res);
var authToken = res.json().token;
localStorage.setItem('authToken', authToken);
let redirectUrlTemp: any;
redirectUrlTemp = this.redirectUrl;
this.redirectUrl = null;
if (!redirectUrlTemp) {
console.log(redirectUrlTemp);
redirectUrlTemp = ['/login'];
}
this.router.navigate(redirectUrlTemp);
},
err => {
//alert(error.text());
console.log(err.text());
});
}
logout(){
// clear token remove user from local storage to log user out
this.token = null;
localStorage.removeItem('authToken');
}
}
when i try to post data using postman it works properly but from angular 2 it not allowing to redirect from next page
Login.component.ts
import { Component, OnInit } from '#angular/core';
import { Router, ActivatedRoute } from '#angular/router';
import { AuthenticationService } from "app/services";
import { LoginRequest } from "app/models/models";
import { AlertService } from 'app/services';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
import { Http, Response } from '#angular/http';
#Component({
moduleId: module.id,
selector: 'login',
templateUrl: 'login.component.html'
})
export class LoginComponent implements OnInit {
model: any = {};
getLogin: LoginRequest[] = [];
loading = false;
error = '';
returnUrl: string;
constructor(
private route: ActivatedRoute,
private router: Router,
private http: Http,
private alertService: AlertService,
private authenticationService: AuthenticationService) { }
login() {
this.loading = true;
this.authenticationService.login(this.model.username, this.model.password).subscribe(data => {
this.router.navigate([this.returnUrl]);
},
error => {
this.alertService.error(error);
this.loading = false;
});
//let redirect = this.authenticationService.redirectUrl ? this.authenticationService.redirectUrl : '/allTask';
}
}
auth.guadr.ts
import { Injectable } from '#angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '#angular/router';
import { AuthenticationService } from "app/services";
#Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private authService: AuthenticationService) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
if (localStorage.getItem('authToken')) {
// logged in so return true
return true;
}
this.authService.redirectUrl =[state.url];
this.router.navigate(['/login']);
return false;
}
}
This error means that navigate array parameter with index 0 is undefined.
In your case you didn't set this.returnUrl in Login.component.ts
this.router.navigate([this.returnUrl]);