🚥
Angular/Ionic + StorybookでNavControllerを使い画面遷移する
画面遷移時のインタラクションを確認するために、Storybook上でNavControllerを使いました。やり方が分からずハマったのでメモ
まず画面遷移ができる状態に
この記事の「サンプル削除」が終わったところから。
まず、
ionic g page hello
で遷移先の画面を作り、homeとhelloで行ったり来たりできるようにします。
- app-routing.module.ts
import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{
path: 'home',
loadChildren: () => import('./home/home.module').then( m => m.HomePageModule)
},
{
path: '',
redirectTo: 'home',
pathMatch: 'full'
},
{
path: 'hello',
loadChildren: () => import('./hello/hello.module').then( m => m.HelloPageModule)
},
];
- home.module.ts
Storybookで使えるようにexportしています。
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { IonicModule } from "@ionic/angular";
import { FormsModule } from "@angular/forms";
import { HomePage } from "./home.page";
import { HomePageRoutingModule } from "./home-routing.module";
@NgModule({
imports: [CommonModule, FormsModule, IonicModule, HomePageRoutingModule],
declarations: [HomePage],
exports: [HomePage],
})
export class HomePageModule {}
- home.page.html
<ion-header>
<ion-toolbar>
<ion-title>home</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-button (click)="toHello()">home</ion-button>
</ion-content>
- home.page.ts
import { Component, OnInit } from "@angular/core";
import { NavController } from "@ionic/angular";
@Component({
selector: "app-hello",
templateUrl: "./hello.page.html",
styleUrls: ["./hello.page.scss"],
})
export class HelloPage implements OnInit {
constructor(private nav: NavController) {}
ngOnInit() {}
public toHome(): void {
this.nav.navigateForward("home");
}
}
helloページの方は、htmlの文言とnavigateForward
がnavigateBack
が違うだけなので割愛。
ionic serve
で画面を立ち上げると、ボタンを押して行ったり来たりできるようになっています。
これをStorybookで
useFactoryでRouterをDIしてみたり色々試したのですが、結論だけ書くと以下のコードで動きます。
import { APP_BASE_HREF, CommonModule } from "@angular/common";
import {
DefaultUrlSerializer,
RouterModule,
Routes,
UrlSerializer,
} from "@angular/router";
import { IonicModule } from "@ionic/angular";
import { moduleMetadata } from "@storybook/angular";
import { HomePageModule } from "./home.module";
import { HomePage } from "./home.page";
const routes: Routes = [
{
path: "home",
loadChildren: () => import("./home.module").then((m) => m.HomePageModule),
},
{
path: "",
redirectTo: "home",
pathMatch: "full",
},
{
path: "hello",
loadChildren: () =>
import("../hello/hello.module").then((m) => m.HelloPageModule),
},
];
//#region モジュール定義
const imports = [
CommonModule,
IonicModule.forRoot(),
RouterModule.forRoot(routes, {
useHash: true,
}),
HomePageModule,
];
const providers = [{ provide: APP_BASE_HREF, useValue: "/" }];
export const data = {
imports,
providers,
};
export default {
title: "pages/HomePage",
excludeStories: /.*[(data)]$/,
decorators: [moduleMetadata(data)],
component: HomePage,
};
//#endregion
const Template = (args: HomePage) => ({
component: HomePage,
props: args,
template: `
<ion-app>
<ion-router-outlet></ion-router-outlet>
</ion-app>
`,
});
export const 画面遷移のテスト = Template.bind({});
ポイントは
- Storybookのiframe内で遷移するので
useHash:true
が必要 - index.htmlにある
<base>
の代わりになる{ provide: APP_BASE_HREF, useValue: "/" },
が必要 -
template
にはapp-home
ではなくion-router-outlet
を使用
といったところでしょうか。インタラクションの確認が必要なときには参考にしてみてください。
Discussion