Реализуйте маршрутизацию с компонентом шагов в динамическом диалоговом окне

Может ли кто-нибудь помочь мне с реализацией компонента шагов в динамическом диалоговом окне в primeng. Я работаю над примером проекта, в котором мне нужно реализовать экран входа в систему в диалоговом окне, которое включает в себя несколько шагов, таких как ввод основной информации на первом этапе, а затем ввод более подробной информации о пользователе на следующих шагах.

Я хотел бы переходить к различным компонентам по мере перехода от одного шага к другому, оставаясь при этом в динамическом диалоговом окне.

Любые общие направления очень ценятся. Спасибо

🤔 А знаете ли вы, что...
Версии Angular выпускаются с учетом совместимости и обратной совместимости, что облегчает обновление приложений на новые версии.


3
180
1

Ответ:

Решено

Я думаю, что это достижимо следующим образом:

Загрузка компонента корневого приложения:

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <h1>Hello from {{ name }}!</h1>
    <router-outlet></router-outlet>
  `,
  imports: [RouterOutlet],
})
export class App {
  name = 'Angular';
}

bootstrapApplication(App, {
  providers: [
    /**
     * DialogService must be provided in the component that is about to open the dialog - the component injector is taken in order to keep router-outlets in the right order
     */
    // DialogService,
    provideAnimations(),
    provideRouter([
      {
        path: '',
        loadComponent: () =>
          import('./components/my-page/my-page.component').then(
            (c) => c.MyPageComponent
          ),
        children: [
          {
            path: '',
            pathMatch: 'full',
            redirectTo: 'step-one',
          },
          {
            path: 'step-one',
            loadComponent: () =>
              import(
                './components/my-page/steps/1-step-one/step-one.component'
              ).then((c) => c.StepOneComponent),
          },
          {
            path: 'step-two',
            loadComponent: () =>
              import(
                './components/my-page/steps/2-step-two/step-two.component'
              ).then((c) => c.StepTwoComponent),
          },
          {
            path: 'step-three',
            loadComponent: () =>
              import(
                './components/my-page/steps/3-step-three/step-three.component'
              ).then((c) => c.StepThreeComponent),
          },
        ],
      },
    ]),
  ],
});

Стиль.scss:

@import 'primeng/resources/themes/lara-light-blue/theme.css';
@import 'primeng/resources/primeng.css';
@import 'primeicons/primeicons.css';
@import 'primeflex/primeflex.css';

Компонент страницы, который будет отображать диалог:

<ng-container
  *ngIf = "dynamicDialog; else dialogTpl"
  [ngTemplateOutlet] = "dynamicDialogTpl"
></ng-container>

<ng-template #dialogTpl>
  <button
    type = "button"
    (click) = "showDialog()"
    pButton
    icon = "pi pi-info-circle"
    label = "Show dialog"
    [disabled] = "dialogVisible"
  ></button>
  <p-dialog position = "top" [(visible)] = "dialogVisible">
    <app-steps-dialog></app-steps-dialog>
  </p-dialog>
</ng-template>

<ng-template #dynamicDialogTpl>
  <button
    type = "button"
    (click) = "showDynamicDialog()"
    pButton
    icon = "pi pi-info-circle"
    label = "Show dynamic dialog"
    [disabled] = "dynamicDialogVisible"
  ></button>
</ng-template>

@Component({
  templateUrl: './my-page.component.html',
  standalone: true,
  imports: [
    ButtonModule,
    DialogModule,
    StepsDialogComponent,
    NgIf,
    NgTemplateOutlet,
  ],
  /**
   * DialogService must be provided in the component that is about to open the dialog - the component injector is taken in order to keep router-outlets in the right order
   */
  providers: [DialogService],
})
export class MyPageComponent implements OnInit {
  /**
   * a switch between dialog an dynamicDialog
   */
  dynamicDialog = true;

  dialogVisible: boolean = true;
  dynamicDialogVisible: boolean = false;

  private destroyRef = inject(DestroyRef);
  private dialogService = inject(DialogService);

  private dynamicDialogRef: DynamicDialogRef | undefined;

  private viewContainerRef = inject(ViewContainerRef);

  ngOnInit() {}

  showDialog(): void {
    if (!this.dynamicDialog) {
      this.dialogVisible = true;
    }
  }

  showDynamicDialog(): void {
    if (this.dynamicDialog) {
      this.dynamicDialogVisible = true;
      this.dynamicDialogRef = this.dialogService.open(StepsDialogComponent, {
        appendTo: this.viewContainerRef.element.nativeElement,
        data: {
          dynamic: true,
        },
      });
      this.dynamicDialogRef.onClose
        .pipe(
          tap(() => {
            this.dynamicDialogVisible = false;
            this.dynamicDialogRef = void 0;
          }),
          takeUntilDestroyed(this.destroyRef)
        )
        .subscribe();
    }
  }
}

Компонент диалогового окна «Шаги»:

<div class = "card">
  <p-steps [model] = "items" [readonly] = "false"></p-steps>
  <router-outlet></router-outlet>
</div>

@Component({
  selector: 'app-steps-dialog',
  templateUrl: './steps-dialog.component.html',
  standalone: true,
  imports: [StepsModule, ButtonModule, RouterOutlet],
})
export class StepsDialogComponent {
  items: MenuItem[] = [
    { label: 'Step One', routerLink: 'step-one' },
    { label: 'Step Two', routerLink: 'step-two' },
    { label: 'Step Three', routerLink: 'step-three' },
  ];

  dynamicDialogConfig = inject(DynamicDialogConfig, { optional: true });

  constructor() {
    console.info('dynamicDialogConfig', this.dynamicDialogConfig);
  }
}

Компонент первого шага:

<h2>Step One</h2>
<div class = "flex justify-content-end">
  <p-button icon = "pi pi-chevron-right" routerLink = "/step-two"></p-button>
</div>

@Component({
  templateUrl: './step-one.component.html',
  standalone: true,
  imports: [RouterLink, ButtonModule],
})
export class StepOneComponent {}

Шаг второй. Компонент:

<h2>Step Two</h2>
<div class = "flex justify-content-between">
  <p-button icon = "pi pi-chevron-left" routerLink = "/step-one"></p-button>
  <p-button icon = "pi pi-chevron-right" routerLink = "/step-three"></p-button>
</div>

@Component({
  templateUrl: './step-two.component.html',
  standalone: true,
  imports: [RouterLink, ButtonModule],
})
export class StepTwoComponent {}

И компонент третьего шага:

<h2>Step Three</h2>
<div class = "flex justify-content-start">
  <p-button icon = "pi pi-chevron-left" routerLink = "/step-two"></p-button>
</div>

@Component({
  templateUrl: './step-three.component.html',
  standalone: true,
  imports: [RouterLink, ButtonModule],
})
export class StepThreeComponent {}

И последнее, но не менее важное :) stackblitz@demo