I am trying to create a provider for our app that contains some configuration for the Android hardware back button and will be passed to the Android back button override upon entering a page. I set up the provider, and injected it into the relevant page through the constructor but find the app is unable to navigate to the page with the provider in it's constructor. Upon removing the injection from the constructor on the page, navigation is again possible.
Here are the errors when attempting to navigate to the page:
Winston Log:
error: undefined {"ngTempTokenPath":null,"ngTokenPath":["Button",null],"__zone_symbol__currentTask":{"type":"microTask","state":"notScheduled","source":"Promise.then","zone":"angular","cancelFn":null,"runCount":0}}
Chrome Dev Tools Log:
ERROR Error: Uncaught (in promise): TypeError: n[r]._updateTaskCount is not a function TypeError: n[r]._updateTaskCount is not a function
Followed by:
Uncaught Error: macroTask 'setTimeout': can not transition to 'running', expecting state 'scheduled', was 'scheduling'.
Questionnare Page
import { Component, ViewChild } from "@angular/core";
import { TranslateService } from "@ngx-translate/core";
import {
IonicPage,
NavController,
NavParams,
ModalController,
Platform,
Navbar
} from "ionic-angular";
import { SitePages } from "@pages";
import { Logger } from "winston";
import { LogProvider, AndroidBackButtonProvider } from "@providers";
import { AlertController } from "ionic-angular";
@IonicPage()
@Component({
selector: "page-questionaire",
templateUrl: "questionaire.html"
})
export class QuestionairePage {
private readonly logger: Logger;
pushPage: any;
translateStrings: any = {};
startDate: any;
endDate: any;
allowedToLeave: boolean = false;
questionRegEx = new RegExp("^Questionaire\\S*");
submissionRegEx = new RegExp("^Submission\\S*");
constructor(
public translate: TranslateService,
public navParams: NavParams,
public navCtrl: NavController,
public modalCtrl: ModalController,
public alertCtrl: AlertController,
public platform: Platform,
private readonly logProvider: LogProvider,
public androidBackButton: AndroidBackButtonProvider
) {
this.logger = this.logProvider.getLogger();
this.startDate = "March 28, 2010";
this.endDate = "April 10, 2010";
this.pushPage = SitePages.Questionaire2;
}
// Reference Navbar Back button and Override navCtrl.pop() to set Nav Guard flag to TRUE
@ViewChild(Navbar) navBar: Navbar;
// After page loads, set back button override
ionViewDidEnter() {
this.allowedToLeave = false;
this.setBackButtonAction();
// Register override for Android hardware back button
this.platform.registerBackButtonAction(
this.androidBackButton.configAndroidBackButton(),
0
);
}
// Navbar Back button override
setBackButtonAction() {
this.navBar.backButtonClick = () => {
this.contextCheck();
this.navCtrl.pop().catch((reason: any) => this.logger.error(reason));
};
}
// Check Navigation context
contextCheck() {
const activeView = this.navCtrl.getActive();
const previousView = this.navCtrl.getPrevious(activeView);
console.log(previousView.component.name);
if (
this.questionRegEx.test(previousView.component.name) ||
this.submissionRegEx.test(previousView.component.name)
) {
this.allowedToLeave = true;
} else {
this.allowedToLeave = false;
}
}
// Get translations for Nav Guard alert
getTranslations() {
this.translate.get("NAV_ALERT_TITLE").subscribe(title => {
this.translateStrings.title = title;
});
this.translate.get("NAV_ALERT_MESSAGE").subscribe(message => {
this.translateStrings.message = message;
});
this.translate.get("NAV_ALERT_CANCEL").subscribe(cancel => {
this.translateStrings.cancel = cancel;
});
this.translate.get("NAV_ALERT_CONTINUE").subscribe(accept => {
this.translateStrings.accept = accept;
});
}
// Nav Guard
ionViewCanLeave() {
if (!this.allowedToLeave) {
this.getTranslations();
return new Promise<any>((resolve, reject) => {
const alert = this.alertCtrl.create({
title: this.translateStrings.title,
message: this.translateStrings.message,
buttons: [
{
text: this.translateStrings.cancel,
role: "cancel",
handler: () => {
alert
.dismiss()
.then(reject)
.catch((reason: any) => this.logger.error(reason));
return false;
}
},
{
text: this.translateStrings.accept,
handler: () => {
alert
.dismiss()
.then(resolve)
.catch((reason: any) => this.logger.error(reason));
return false;
}
}
]
});
alert.present().catch((reason: any) => this.logger.error(reason));
});
} else {
this.allowedToLeave = false;
return true;
}
}
nextQuestion() {
this.allowedToLeave = true;
this.navCtrl
.push(this.pushPage)
.then(() => this.logger.info("Navigating to : Next question..."))
.catch((reason: any) => this.logger.error(reason));
}
presentHelpModal() {
this.logger.info("Click Received");
const helpModal = this.modalCtrl.create(SitePages.HelpModal);
helpModal
.present()
.then(() => this.logger.info("Help Modal Displayed"))
.catch((reason: any) => this.logger.error(reason));
}
}
Android Back Button Provider
import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
import {
Keyboard,
NavController,
Platform,
IonicApp,
Menu
} from "../../../node_modules/ionic-angular";
import { LogProvider } from "../log/log";
import { Logger } from "winston";
/*
Generated class for the AndroidBackButtonProvider provider.
See https://angular.io/guide/dependency-injection for more info on providers
and Angular DI.
*/
@Injectable()
export class AndroidBackButtonProvider {
private readonly logger: Logger;
constructor(
public http: HttpClient,
public keyboard: Keyboard,
public ionicApp: IonicApp,
public navCtrl: NavController,
public platform: Platform,
public menuCtrl: Menu,
public logProvider: LogProvider
) {
console.log("Hello AndroidBackButtonProvider Provider");
this.logger = this.logProvider.getLogger();
}
configAndroidBackButton(): Function {
if (this.keyboard.isOpen()) {
// Handles the keyboard if open
this.keyboard.close();
return;
}
const activePortal =
this.ionicApp._loadingPortal.getActive() ||
this.ionicApp._modalPortal.getActive() ||
this.ionicApp._toastPortal.getActive() ||
this.ionicApp._overlayPortal.getActive();
//activePortal is the active overlay like a modal,toast,etc
if (activePortal) {
activePortal.dismiss().catch((reason: any) => this.logger.error(reason));
return;
} else if (this.menuCtrl.isOpen) {
// Close menu if open
this.menuCtrl.close().catch((reason: any) => this.logger.error(reason));
return;
} else {
this.navCtrl.pop().catch((reason: any) => this.logger.error(reason));
}
}
}
Any assistance would be greatly appreciated.
Aucun commentaire:
Enregistrer un commentaire