LoginSignup
14
1

More than 1 year has passed since last update.

ダイアログにURLを持たせたい!

Last updated at Posted at 2021-12-15

やりたいこと

🎅 ダイアログコンポーネントに一意のURLを持たせ、そのURLにアクセスした時にダイアログを自動で開きたい
🎅 ダイアログページをURL共有できるようにしたい
🎅 ブラウザをリロードしてもダイアログが開いた状態を保ちたい
例えば
http://myurl?id=123へアクセス
→ IDが123のデータをAPIリクエストし、その結果を載せたダイアログコンポーネントを開く

(ダイアログを使わない方が楽にできる気がしますが、
アプリケーション内の操作方法を統一したいなどの諸事情により今回はこのような実装にしました)

環境

  • Angular 13
  • Angular Material

早速つくっていきます

1. ダイアログの親コンポーネントのngOnInitのタイミングでダイアログを開く

@Component({
  selector: 'app-my-table',
  templateUrl: './my-table.component.html',
  styleUrls: ['./my-table.component.sass'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MyTableComponent implements OnInit {
  constructor(
    private route: ActivatedRoute,
    private router: Router,
    public dialog: MatDialog,
    private http: HttpClient
  ) {}

  ngOnInit(): void {
    this.route.queryParams
      .pipe(
// 🎅クエリパラメータに特定のパラメータ(今回はid)が含まれるときのみダイアログを開く
        filter(({ id }) => id),
// 🎅クエリパラメータから取得したIDでデータを取得、ダイアログコンポーネントに渡す
        switchMap(({ id }) => this.http.get<MyData>(`${myURL}/${id}`)),
        switchMap((myData) => {
          return this.dialog
            .open(MyDialogComponent, {
// 🎅今回はダイアログを普通のページっぽく見せたいのでheight, widthを100%にして、背景を見えないようにする
              data: myData,
              height: '100%',
              width: '100%',
              disableClose: true,
            })
// 🎅ダイアログを閉じた後は任意のページに遷移させる
            .afterClosed()
            .pipe(
              tap(() => {
                this.router.navigate(['/myURL']);
              })
            );
        })
      )
      .subscribe();
  }
}

2. ダイアログが開くまでの間スピナーを表示する

ダイアログに表示するデータが返ってくるまでに時間がかかる場合、overlay+spinnerを使ってユーザの操作を制限

@Component({
  selector: 'app-my-table',
  templateUrl: './my-table.component.html',
  styleUrls: ['./my-table.component.sass'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MyTableComponent implements OnInit {
  // 🎅追加
  overlayRef = this.overlay.create({
    hasBackdrop: true,
    positionStrategy: this.overlay.position().global()![Something went wrong]()
.centerHorizontally().centerVertically(),
  });

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    public dialog: MatDialog,
    private overlay: Overlay, // 🎅追加
    private http: HttpClient
  ) {}

  ngOnInit(): void {
    this.route.queryParams
      .pipe(
        filter(({ id }) => id),
        switchMap(({ id }) => {
// 🎅APIからのリスポンスが返ってくるまでの間スピナーを表示
          this.overlayRef.attach(new ComponentPortal(MatSpinner));
          return this.http.get<MyData>(`${myURL}/${id}`);
        }),
        switchMap((myData) => {
// 🎅スピナーを非表示にしてダイアログを開く
          this.overlayRef.detach();
          return this.dialog.open()
          ...

        })
      )
      .subscribe();
  }
}

最終結果

URLに?id=123を追加すると、ダイアログコンポーネントが開いてくれました!
(※URL部分がわかりやすいように一部を切り取っているためスピナーの位置がずれています)
ezgif.com-gif-maker (2).gif

14
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
1