Ionic 3. 没有 NavController 的提供者
Ionic 3. No provider for NavController
我的问题与找到的问题相似 here
但我不确定他的情况是否相同,因为有时当我停止应用程序并使用 ionic serve 重新启动时错误会消失。错误returns 再次随机返回。我注意到,当我在 app.component.ts 构造函数中使用调试器语句时,我可以绕过错误。任何帮助,将不胜感激。谢谢。
这是我的代码
app.component.ts
export class MyApp {
@ViewChild('content') nav: Nav;
rootPage: any = HomePage;
pages: Array<{ title: string, component: any }>;
constructor(public platform: Platform,
public statusBar: StatusBar,
public splashScreen: SplashScreen) {
this.initializeApp();
this.pages = [
{ title: 'Dashboard', component: DashboardPage },
];
debugger
}
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.
this.statusBar.styleDefault();
this.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);
}
}
app.html
<ion-menu [content]="content">
<ion-header>
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<button menuClose ion-item *ngFor="let p of pages" (click)="openPage(p)">
{{p.title}}
</button>
</ion-list>
</ion-content>
</ion-menu>
<ion-nav #content swipeBackEnabled="false" [root]="rootPage"></ion-nav>
home.ts
export class HomePage {
token: string;
constructor(public navCtrl: NavController,
public menuCtrl: MenuController,
public storage: Storage) {
setTimeout(() => {
this.storage.get('_token').then((token) => {
this.token = token;
if (this.token && this.token.length > 0) {
this.navCtrl.setRoot(DashboardPage)
} else {
this.navCtrl.setRoot(LoginPage)
}
}).catch((error) => {
console.log(error);
this.navCtrl.setRoot(LoginPage)
});
}, 1000)
}
ionViewWillEnter() {
this.menuCtrl.enable(false);
}
ionViewWillLeave() {
this.menuCtrl.enable(true);
}
}
login.ts
export class LoginPage {
username: string;
password: string;
constructor(public navCtrl: NavController,
public navParams: NavParams,
public userProvider: UserProvider,
public storage: Storage,
public alertCtrl: AlertController,
public menuCtrl: MenuController) {
}
ionViewDidLoad() {
console.log('ionViewDidLoad LoginPage');
}
login() {
console.log("Logging in...", this.username, this.password);
var credentials = { 'email': this.username, 'password': this.password };
this.userProvider.login(credentials).then((validResponse: any) => {
console.log('success', validResponse);
var data = validResponse.data;
this.storage.set('_token', data.token);
this.navCtrl.setRoot(DashboardPage);
}).catch((errorResponse: any) => {
console.log('error', errorResponse);
var title = '';
var subTitle = '';
title = "Oops!"
if (errorResponse.status == 401) {
subTitle = "Invalid Username/Password";
} else {
var errorObject = errorResponse.error;
if (errorObject.errors) {
for (let error of errorObject.errors) {
subTitle += error + '. ';
}
} else {
subTitle = errorResponse.message;
}
}
this.presentAlert(title, subTitle);
});
}
presentAlert(title, subTitle) {
let alert = this.alertCtrl.create({
title: title,
subTitle: subTitle,
buttons: ['Ok']
});
alert.present();
}
ionViewWillEnter() {
this.menuCtrl.enable(false);
}
ionViewWillLeave() {
this.menuCtrl.enable(true);
}
}
login.html
<ion-content padding>
<div class="login-holder">
<ion-img class="logo" width="120" src="../../assets/imgs/logo.png"></ion-img>
<br>
<ion-img class="hero" width="250" src="../../assets/imgs/restaurant.png"></ion-img>
<ion-input class="username" [(ngModel)]="username" type="text" placeholder="Phone or Email"></ion-input>
<ion-input class="password" [(ngModel)]="password" type="password" placeholder="Password"></ion-input>
<button class="login" ion-button full (click)="login()">Login</button>
</div>
</ion-content>
我的流程是这样的,HomePage是进入登录页面之前的临时屏幕,
超时后,我转到登录页面或仪表板页面,具体取决于它们是否已经在本地存储中拥有令牌。从登录页面,我将用户带到仪表板页面。
由于我是 angular 和 ionic 的新手,所以我什至不确定自己是否做对了。我已经研究了堆栈溢出中的所有类似问题。
- 他们中的大多数人通过在构造函数中传递 App 模块并从应用程序中检索 navcontroller 获得了解决方案。但这对我不起作用。
- 有人建议检查导入路径,所以我与文档和启动项目交叉验证它似乎是正确的。
- 有些人建议删除构造函数中传递的导航控制器,但如果你检查我的代码,我没有在构造函数中传递 app.component.ts 我只传递了页面的构造函数,它位于 ionic 生成的骨架代码中生成页面命令。
再次感谢您的宝贵时间。
将您的 Home.ts 更改为:
export class HomePage {
token: string;
constructor(public navCtrl: NavController,
public menuCtrl: MenuController,
public storage: Storage) {
}
ionViewWillEnter() {
this.menuCtrl.enable(false);
}
ionViewWillLeave() {
this.menuCtrl.enable(true);
}
ionViewDidLoad() {
setTimeout(() => {
this.storage.get('_token').then((token) => {
this.token = token;
if (this.token && this.token.length > 0) {
this.navCtrl.setRoot(DashboardPage)
} else {
this.navCtrl.setRoot(LoginPage)
}
}).catch((error) => {
console.log(error);
this.navCtrl.setRoot(LoginPage)
});
}, 1000)
}
}
看了一会儿。我发现了问题。我的 home.ts 中缺少 @IonicPage 装饰器。添加后解决。
我的问题与找到的问题相似 here
但我不确定他的情况是否相同,因为有时当我停止应用程序并使用 ionic serve 重新启动时错误会消失。错误returns 再次随机返回。我注意到,当我在 app.component.ts 构造函数中使用调试器语句时,我可以绕过错误。任何帮助,将不胜感激。谢谢。
这是我的代码
app.component.ts
export class MyApp {
@ViewChild('content') nav: Nav;
rootPage: any = HomePage;
pages: Array<{ title: string, component: any }>;
constructor(public platform: Platform,
public statusBar: StatusBar,
public splashScreen: SplashScreen) {
this.initializeApp();
this.pages = [
{ title: 'Dashboard', component: DashboardPage },
];
debugger
}
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.
this.statusBar.styleDefault();
this.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);
}
}
app.html
<ion-menu [content]="content">
<ion-header>
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<button menuClose ion-item *ngFor="let p of pages" (click)="openPage(p)">
{{p.title}}
</button>
</ion-list>
</ion-content>
</ion-menu>
<ion-nav #content swipeBackEnabled="false" [root]="rootPage"></ion-nav>
home.ts
export class HomePage {
token: string;
constructor(public navCtrl: NavController,
public menuCtrl: MenuController,
public storage: Storage) {
setTimeout(() => {
this.storage.get('_token').then((token) => {
this.token = token;
if (this.token && this.token.length > 0) {
this.navCtrl.setRoot(DashboardPage)
} else {
this.navCtrl.setRoot(LoginPage)
}
}).catch((error) => {
console.log(error);
this.navCtrl.setRoot(LoginPage)
});
}, 1000)
}
ionViewWillEnter() {
this.menuCtrl.enable(false);
}
ionViewWillLeave() {
this.menuCtrl.enable(true);
}
}
login.ts
export class LoginPage {
username: string;
password: string;
constructor(public navCtrl: NavController,
public navParams: NavParams,
public userProvider: UserProvider,
public storage: Storage,
public alertCtrl: AlertController,
public menuCtrl: MenuController) {
}
ionViewDidLoad() {
console.log('ionViewDidLoad LoginPage');
}
login() {
console.log("Logging in...", this.username, this.password);
var credentials = { 'email': this.username, 'password': this.password };
this.userProvider.login(credentials).then((validResponse: any) => {
console.log('success', validResponse);
var data = validResponse.data;
this.storage.set('_token', data.token);
this.navCtrl.setRoot(DashboardPage);
}).catch((errorResponse: any) => {
console.log('error', errorResponse);
var title = '';
var subTitle = '';
title = "Oops!"
if (errorResponse.status == 401) {
subTitle = "Invalid Username/Password";
} else {
var errorObject = errorResponse.error;
if (errorObject.errors) {
for (let error of errorObject.errors) {
subTitle += error + '. ';
}
} else {
subTitle = errorResponse.message;
}
}
this.presentAlert(title, subTitle);
});
}
presentAlert(title, subTitle) {
let alert = this.alertCtrl.create({
title: title,
subTitle: subTitle,
buttons: ['Ok']
});
alert.present();
}
ionViewWillEnter() {
this.menuCtrl.enable(false);
}
ionViewWillLeave() {
this.menuCtrl.enable(true);
}
}
login.html
<ion-content padding>
<div class="login-holder">
<ion-img class="logo" width="120" src="../../assets/imgs/logo.png"></ion-img>
<br>
<ion-img class="hero" width="250" src="../../assets/imgs/restaurant.png"></ion-img>
<ion-input class="username" [(ngModel)]="username" type="text" placeholder="Phone or Email"></ion-input>
<ion-input class="password" [(ngModel)]="password" type="password" placeholder="Password"></ion-input>
<button class="login" ion-button full (click)="login()">Login</button>
</div>
</ion-content>
我的流程是这样的,HomePage是进入登录页面之前的临时屏幕, 超时后,我转到登录页面或仪表板页面,具体取决于它们是否已经在本地存储中拥有令牌。从登录页面,我将用户带到仪表板页面。
由于我是 angular 和 ionic 的新手,所以我什至不确定自己是否做对了。我已经研究了堆栈溢出中的所有类似问题。
- 他们中的大多数人通过在构造函数中传递 App 模块并从应用程序中检索 navcontroller 获得了解决方案。但这对我不起作用。
- 有人建议检查导入路径,所以我与文档和启动项目交叉验证它似乎是正确的。
- 有些人建议删除构造函数中传递的导航控制器,但如果你检查我的代码,我没有在构造函数中传递 app.component.ts 我只传递了页面的构造函数,它位于 ionic 生成的骨架代码中生成页面命令。
再次感谢您的宝贵时间。
将您的 Home.ts 更改为:
export class HomePage {
token: string;
constructor(public navCtrl: NavController,
public menuCtrl: MenuController,
public storage: Storage) {
}
ionViewWillEnter() {
this.menuCtrl.enable(false);
}
ionViewWillLeave() {
this.menuCtrl.enable(true);
}
ionViewDidLoad() {
setTimeout(() => {
this.storage.get('_token').then((token) => {
this.token = token;
if (this.token && this.token.length > 0) {
this.navCtrl.setRoot(DashboardPage)
} else {
this.navCtrl.setRoot(LoginPage)
}
}).catch((error) => {
console.log(error);
this.navCtrl.setRoot(LoginPage)
});
}, 1000)
}
}
看了一会儿。我发现了问题。我的 home.ts 中缺少 @IonicPage 装饰器。添加后解决。