Ionic3 framework network.onConnect().subscribe not working? - ionic-framework

I have created a little phone app with Ionic. I am trying to implement a bit logic where the component knows when its online or offline. To do so I am using the network plugin fom Ionic and it just does not work as expected.
instead of updating the
this.connected
value every time when I switch on / off the network, it will only do so if I switch it off / on AND do something like switching from landscape to portrait mode, or work on a different app for a while and come back to the app.
Really puzzled by that.
Here is the code:
import {Component} from '#angular/core';
import {NavController, NavParams, Platform} from 'ionic-angular';
import {GooglePlus} from '#ionic-native/google-plus';
import {SurveyService} from "./survey.service";
import {Survey} from "../../Declarations/Survey";
import {SurveyPage} from "../survey/survey";
import {Network} from "#ionic-native/network";
#Component({
selector: 'page-home',
templateUrl: 'home.html',
providers: [SurveyService, Network]
})
export class HomePage {
public surveys: Survey[] = [];
public connected;
public networkType;
constructor(public navCtrl: NavController,
private googlePlus: GooglePlus,
private surveyService: SurveyService,
public navParams: NavParams,
platform: Platform,
private network: Network) {
this.checkForNetwork();
this.surveyService.getAvailable().subscribe(surveys => {
this.checkForNetwork();
this.surveys = surveys;
})
}
login() {
this.googlePlus.login({
'webClientId': '632130231957-dmjd154jhq1eenimedri3m0de6sh7tln.apps.googleusercontent.com'
}).then((res) => {
console.log(res);
}, (err) => {
console.log(err);
});
}
logout() {
this.googlePlus.logout().then(() => {
console.log("logged out");
});
}
openSurvey = (survey: Survey) => {
this.navCtrl.push(SurveyPage, {
survey: survey
});
}
checkForNetwork = () => {
this.networkType= this.network.type;
this.network.onDisconnect().subscribe(() => {
this.connected = false;
this.network.type = null;
});
this.network.onConnect().subscribe(() => {
this.connected = 'network connected!';
setTimeout(() => {
if (this.network.type === 'wifi') {
this.connected = true;
}
}, 3000);
});
}
}

OK, I worked it out:
Turns out that ionic works perfectly fine, but I tried to change the view of my application depending on whether
this.connected
is true or false. I did not realize that I needed to tell Angular to refresh its view by using Application
applicationRef.tick();
in the right place. So basically, once the Ionic changes the value of this.connected you need to tell Angular about it, here is the corrected part of the code:
You need to inject ApplicationRef into the constructor
constructor(public navCtrl: NavController,
...
private appReference: ApplicationRef) {
...
checkForNetwork = () => {
this.networkType= this.network.type;
this.network.onDisconnect().subscribe(() => {
this.connected = false;
this.network.type = null;
this.appReference.tick();
});
this.network.onConnect().subscribe(() => {
this.connected = 'network connected!';
setTimeout(() => {
if (this.network.type === 'wifi') {
this.connected = true;
this.appReference.tick();
}
}, 3000);
});
}

Related

Rest web service returns null value on mobile device but works on PC in Ionic App

i am consuming Rest JSONP Web Service in an ionic App which works fine on PC but returns null value on mobile devices
My page.ts file
import {
Component,
OnInit
} from '#angular/core';
import {
AlertController,
LoadingController
} from '#ionic/angular';
import {
ActionSheetController
} from '#ionic/angular';
import {
Router
} from '#angular/router'
import {
ProApiService
} from './../../../../services/pro-api.service';
#Component({
selector: 'app-ranked-diagnosis',
templateUrl: './ranked-diagnosis.page.html',
styleUrls: ['./ranked-diagnosis.page.scss'],
})
export class RankedDiagnosisPage implements OnInit {
tabSelect: string = 'show10';
show10Data: Array < any >= [];
showAllData: Array < any >= [];
redFlagsData: Array < any >= [];
loading: any;
constructor(
private api: ProApiService,
public alertController: AlertController,
public loadingController: LoadingController,
public actionSheetController: ActionSheetController,
private router: Router
) {}
segmentChanged(event: any) {
this.tabSelect = event.detail.value;
}
async presentActionSheet(buttons) {
const actionSheet = await this.actionSheetController.create({
header: 'Sub Diagnosis',
buttons: buttons
});
await actionSheet.present();
}
async presentAlert(msg: string, header: string) {
const alert = await this.alertController.create({
header: '',
subHeader: header,
message: msg,
buttons: ['OK']
});
await alert.present();
}
async presentLoading() {
this.loading = await this.loadingController.create({
message: 'loading...',
});
return await this.loading.present();
}
ngOnInit() {
}
ionViewWillEnter() {
if (this.api.ProApiData.diagnoses_checklist.diagnoses) {
this.showAllData =
this.api.ProApiData.diagnoses_checklist.diagnoses;
for (let i = 0; i < 10; i++) {
this.show10Data.push(this.showAllData[i]);
}
this.showAllData.forEach(item => {
if (item.red_flag == 'true') {
this.redFlagsData.push(item);
}
});
console.log(this.showAllData);
} else {
console.log('error');
this.router.navigateByUrl('isabel-pro');
}
}
why_diagnosis(url: any, weightage: any) {
this.presentLoading();
this.api.why_diagnosisApi(url).subscribe(res => {
let matched_terms = res._body.why_diagnosis.matched_terms;
console.log(matched_terms);
let alertMsg = `We matched the terms: ${matched_terms}<br><hr>Degree of match between query entered and database: ${weightage}`;
this.presentAlert(alertMsg, 'Why did this diagnosis come up ?');
this.loadingController.dismiss();
}, err => {
this.loadingController.dismiss();
console.log('error');
});
}
}
in the above code i am calling why_diagnosis function which calls the function from a service file.
My service.ts file
import {
Injectable
} from '#angular/core';
import {
HttpClient,
HttpHeaders
} from '#angular/common/http';
import {
Jsonp
} from '#angular/http';
import {
Observable
} from 'rxjs';
import {
map
} from 'rxjs/operators';
import {
ConstantsService
} from './../../../services/constants.service';
#Injectable({
providedIn: 'root'
})
export class ProApiService {
apiRoot = this.root.APIroot;
diagnosisPROData: any;
drugData: any;
ProApiData: any;
drugApiData: any;
constructor(
private jsonp: Jsonp,
private http: HttpClient,
private root: ConstantsService) {}
why_diagnosisApi(url: any): Observable < any > {
let whyUrl = `${this.apiRoot}Mob_isabelPRO.php?
why_url=${url}&callback=JSONP_CALLBACK`;
return this.jsonp.request(whyUrl, 'callback')
.pipe(
map(
res => {
let why_diagnosis = res;
return why_diagnosis;
}
)
);
}
}
above code is from my service file.
this is the value i am getting in PC
this is the return on mobile
i dont know whats wrong with it. please suggest me the solution
Thanks

Cannot use namespace 'NavController'',NgZone',Google,as a type

I am new to ionic app developer, and I am facing this issue: when I open one Component, it is showing error messages, i.e, cannot use namespace as type ionic(NgZone,NavController and googlePlus). Why am I getting this error message?
Here is my code:
export class HomePage {
userProfile: any = null;
zone: NgZone;
constructor(public navCtrl: NavController, private googlePlus: GooglePlus) {
this.zone = new NgZone({});
firebase.auth().onAuthStateChanged( user => {
this.zone.run( () => {
if (user){
this.userProfile = user;
} else {
this.userProfile = null;
}
});
});
}
}
Maybe you forgot to update your project's package. Please try with:
npm install / npm update
Try the Below code : ( The NgZone object can be created as below )
export class HomePage {
userProfile: any = null;
zone: NgZone;
constructor(public navCtrl: NavController, private googlePlus: GooglePlus, private ngZone: NgZone) {
this.zone = ngZone;
firebase.auth().onAuthStateChanged( user => {
this.zone.run( () => {
if (user){
this.userProfile = user;
} else {
this.userProfile = null;
}
});
});
}
}

Events in Ionic v4

I'm using Ioni v4Beta and I'm traying to update the sidemenu when the user is login.
I search but the usual solution is use Events:
Ionic 3 refresh side menu after login
https://ionicframework.com/docs/api/util/Events/
But in the new version I don't find it, and I don't know how to do it
https://beta.ionicframework.com/docs/api
Thanks a lot, but I finally find how to import it:
import { Events } from '#ionic/angular';
Example on how to do it with subjects:
export const someEvent:Subject = new Subject();
export class ReceivingClass implements OnDestroy, OnInit
{
private someEventSubscription:Subscription;
public OnInit():void{
someEventSubscription = someEvent.subscribe((data) => console.log(data);
}
public onDestroy():void{
someEvent.unsubscribe();
}
}
export class SendingClass implements OnInit
{
public OnInit():void{
setTimeout(() => {
someEvent.next('hi');
}, 500);
}
}
Are you aware that Ionic v4 events will be deprecated soon?
I was also trying to update the sidemenu when a user logs in as well, so i tried using: import { Events } from '#ionic/angular';
However I got a warning referring me to this link https://angular.io/guide/observables#basic-usage-and-terms which I failed to follow because am not that familiar with observables.
After much research I found that I can still use events but I had to import them from angular's router directive.
This was my code before:
/* import was */
import { Events } from '#ionic/angular';
import { Storage } from '#ionic/storage';//ignore this import if doesn't apply to your code
/* inside the class */
constructor(
private events: Events,
private storage: Storage
) {
this.events.subscribe("updateMenu", () => {
this.storage.ready().then(() => {
this.storage.get("userLoginInfo").then((userData) => {
if (userData != null) {
console.log("User logged in.");
let user = userData.user;
console.log(user);
}
else {
console.log("No user found.");
let user = {};
}
}).catch((error)=>{
console.log(error);
});
}).catch((error)=>{
console.log(error);
});
});
}
changes i made that actually got my code working and deprecation warning gone:
/* import is now */
import { Router,RouterEvent } from '#angular/router';
import { Storage } from '#ionic/storage';//ignore this import if it does't apply to your code
Rest of code
constructor(
public router: Router,
public storage: Storage
){
this.router.events.subscribe((event: RouterEvent) => {
this.storage.ready().then(() => {
this.storage.get("userLoginInfo").then((userData) => {
if (userData != null) {
/*console.log("User logged in.");*/
let user = userData.user;
/*console.log(this.user);*/
}
else {
/*console.log("No user found.");*/
let user = {};
}
}).catch((error)=>{
console.log(error);
});
}).catch((error)=>{
console.log(error);
});
});
}
I got the idea after seeing this https://meumobi.github.io/ionic/2018/11/13/side-menu-tabs-login-page-ionic4.html. I hope my answer can be useful.
Steps to resolve the issue
import events in login page and in sidemenu view
In login page, after login success do your logic to publish the events.
for eg:
this.authService.doLogin(payload).subscribe((response) => {
if (response.status) {
this.storage.set('IS_LOGGED_IN', true);
this.events.publish('user:login');
}
}, (error) => {
console.log(error);
});
In sidemenu view, create a listener to watch the events 'user:login'
for eg:
this.menus = [];
// subscribe events
this.events.subscribe('user:login', () => {
// DO YOUR LOGIC TO SET THE SIDE MENU
this.setSidemenu();
});
// check whether the user is logged in or not
checkIsUserloggedIn() {
let isLoggedIn = false;
if (this.storage.get('IS_LOGGED_IN') == '' ||
this.storage.get('IS_LOGGED_IN') == null ||
this.storage.get('IS_LOGGED_IN') == undefined) {
isLoggedIn = false;
} else {
isLoggedIn = true;
}
return isLoggedIn;
}
// to set your sidemenus
setSidemenu() {
let isUserLoggedIn = this.checkIsUserloggedIn();
if(isUserLoggedIn) {
this.menus = ['Home', 'Aboutus', 'Contactus', 'My Profile', 'Logout'];
} else {
this.menus = ['Login', 'Home', 'Aboutus', 'Contactus'];
}
}

IONIC-3 NavController throwing can't resolve all parameters error

I have an interesting problem with IONIC-3 that I've not been able to solve. I am attempting to implement an auth routing which is triggered by ionViewCanEnter. However, while I can pass one nav setter, it will not allow multiple. Here is the code:
AuthService Function:
isAuthenticated(nav: NavController): boolean | Promise<any> {
const userAuth = this.uData.getAuthenticated;
const userProfile = this.uData.getUserProfile;
if (userAuth ) {
//User is logged in, so let's check a few things.
if (!userProfile.sign_up_complete) {
//User has not completed sign up
setTimeout(() => { nav.setRoot(CreateAccountPage) }, 0);
}
return true
} else {
//User is not authenticated, return to walkthrough
setTimeout(() => { nav.setRoot(WalkthroughPage) }, 0);
return false
}}
Example calling:
ionViewCanEnter(): boolean | Promise<any> {
return this.auth.isAuthenticated(this.nav);
}
If I have only CreateAccountPage, the script runs fine. However, when I add WalkthroughPage, it throws the following error:
Error: Can't resolve all parameters for ListingPage: (?, [object Object], [object Object], [object Object]).
Which is an error related to the AuthService. For clarity the WalkthroughPage code is as follows:
import { Component, ViewChild } from '#angular/core';
import { IonicPage, NavController, Slides } from 'ionic-angular';
import { RemoteConfigProvider } from '../../providers/remote-config/remote-config';
import { LoginPage } from '../login/login';
import { SignupPage } from '../signup/signup';
#IonicPage()
#Component({
selector: 'walkthrough-page',
templateUrl: 'walkthrough.html'
})
export class WalkthroughPage {
lastSlide = false;
sign_up_enabled: null;
sign_in_enabled: null;
#ViewChild('slider') slider: Slides;
constructor(public nav: NavController,
public remoteConfig: RemoteConfigProvider) {
}
ionViewDidLoad() {
this.remoteConfig.getValue('sign_up_enabled').then(t => {
this.sign_up_enabled = t;
})
this.remoteConfig.getValue('sign_in_enabled').then(t => {
this.sign_in_enabled = t;
})
}
skipIntro() {
this.lastSlide = true;
this.slider.slideTo(this.slider.length());
}
onSlideChanged() {
this.lastSlide = this.slider.isEnd();
}
goToLogin() {
this.nav.push(LoginPage);
}
goToSignup() {
this.nav.push(SignupPage);
}
}
I have attempted to compare both pages, but not identified the exact cause. I welcome any thoughts.
For those who encounter a similar issue, the fix was straight forward. I simply used deep-linking reference which resolved all issues. Example below.
isAuthenticated(nav: NavController): boolean | Promise<any> {
const userAuth = this.userStore.getAuthenticated;
const userProfile = this.userStore.getUserProfile;
if (userAuth) {
return true
} else {
console.log('Auth guard: Not authenticated');
setTimeout(() => { nav.setRoot('no-access') }, 0);
return false
}
}

Ionic2 navController pop with params (CallBack)

I want to make a callback between two page.
In the page 1, i have this code:
DataInfo= [
{
Price: 0,
ClosePrice: 0,
UpdateTime:"",
DefaultPrice:0
}
]
GetClosePrice(i):number{
return DataInfo[i].ClosePrice;
}
i want to get the value of 'i' from the page 2, How can i load the function GetClosePrice() when the navcontroller return to the page 1 (this.navCtrl.pop())
SOURCE PAGE CLASS
this.navCtrl.push(Page,
{
data: this.data,
callback: this.getData
});
getData = data =>
{
return new Promise((resolve, reject) => {
for (let order of orders) {
this.data = data;
}
resolve();
});
};
TARGET PAGE CLASS
constructor(public navCtrl: NavController, public navParams: NavParams)
{
this.callback = this.navParams.get('callback');
this.data = this.navParams.get('data') || [];
}
sendData(event: any): void
{
this.callback(this.data).then( () => { this.navCtrl.pop() });
}
TARGET PAGE TEMPLATE
<button ion-button (click)="sendData($event)">
I answered similar question in Ionic forum. I just used Events listeners to achieve this behaviour.
MainPage-
import { NavController, Events } from 'ionic-angular';
import { OtherPage } from '../other/other';
export class MainPage{
constructor(private navCtrl: NavController,
private events: Events) { }
private pushOtherPage(){
this.events.subscribe('custom-user-events', (paramsVar) => {
// Do stuff with "paramsVar"
this.events.unsubscribe('custom-user-events'); // unsubscribe this event
})
this.navCtrl.push(OtherPage); // Push your "OtherPage"
}
}
OtherPage-
export class OtherPage {
// Under some function
this.navCtrl.pop().then(() => {
// Trigger custom event and pass data to be send back
this.events.publish('custom-user-events', myCustomParams);
});
}
Try this one - ionic2 pop with params