Davtho1983
Davtho1983

Reputation: 3954

How to implement routing with Angular 4 Material dialogs

I want to allow people to fill out an enquiry form on my web-app that is opened in a modal dialog. First tho, I want people to read a disclaimer about the sort of enquiries I will field.

I want to do this in Angular 4 with Material dialogs via routing, but how do I set up separate routing for my dialogs? Is this even possible? I'm thinking of a kind of wizard structure, where you read one page, which is defined by one component, and then you click 'next' and go to the next component, until you get to the end and it exits the wizard? All of this time, the main web-app needs to be unavailable to interact with.

My HTML for my dialog component is:

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="535px" height="906.5px" viewBox="0 0 535 906.5" enable-background="new 0 0 535 906.5" xml:space="preserve">
<g>
    <path fill="#5BC8AF" d="M534.5,888.5v-876c0-6.627-5.373-12-12-12h-511C6.06,0.5,1.472,4.123,0,9.085
        c-0.321,1.083-0.5,2.228-0.5,3.415v876c0,1.188,0.179,2.331,0.5,3.414c1.15,3.88,4.206,6.936,8.085,8.086
        c1.083,0.321,2.228,0.5,3.415,0.5h511c1.188,0,2.331-0.179,3.414-0.5C530.877,898.528,534.5,893.939,534.5,888.5z"/>
</g>
<g>
    <g>
        <polygon fill="#67327A" points="85.333,709 99.333,694.334 98,676.334 80,679.667 46,672.334 0,706.333 0,798.334 43.333,763       
            "/>
        <polygon fill="#67327A" points="528,649.667 502,647 484.667,664.334 487.333,679.667 476.667,675.667 466.667,681.667 
            455.333,673 434.667,671.667 427.333,695.667 430.667,709 419.333,731 436.667,755 388,787.667 390,776.334 387.333,759.667 
            374,756.334 359.333,765.667 350.667,747.667 337.333,749 324,676.334 309.333,666.334 292.667,674.334 293.333,693.667 
            288.667,719 286,702.334 273.333,693.667 263.333,695 249.333,712.334 248.666,748.334 229.333,729.667 212,727.667 193.333,755 
            196.666,786.334 189.333,779 162.666,768.334 149.333,787 148,807.667 140,802.334 127.333,808.334 118,801 97.333,798.334 
            88.667,815 98,837 86,837.667 82,859.667 76.667,861 60.667,837 44,840.334 40,829 35.333,825.667 46,815 42,797.667 
            23.333,789.667 0,798.334 0,878 0,888 0,907.5 535,907.5 535,888 535,878 535,658.334      "/>
    </g>
    <polygon fill="#67327A" points="0,0 0,13 0,29.5 0,130 7,123 9.5,85 17.5,98 34,106.5 51.5,83 54.5,68.5 61,74.5 70.5,66.5 
        89.5,76.5 79.5,78.5 81,97 99.5,108.5 118.5,98.5 82.5,133 57,163 38,185 43.5,217 78,223 153,175 158,193.5 178,198.5 189,189.5 
        195.5,207.5 207,210 219.5,278.5 236,287 254,279.5 256,244.5 274.5,262.5 288,258.5 300,234.5 300,202 318.5,227 330.5,230 
        350,204.5 353,170.5 359,179.5 385,182.5 400,164.5 398,146.5 409.5,154 420.5,147 429.5,153.5 452,155.5 459,132.5 456,118.5 
        467.5,97 451,74 497.5,40.5 494.5,51.5 496.5,68 512.5,72.5 527.5,62 535,80 535,29.5 535,13 535,0     "/>
</g>
<g class="next-button">
    <rect x="403" y="789" fill="#67327A" width="125" height="99"/>
    <text transform="matrix(1 0 0 1 413 821)" fill="#5BC8AF" font-family="'Bungee-Regular'" font-size="36">next</text>
    <polygon fill="#5BC8AF" points="484,839.5 484,852 415,852 415,852.626 415,863.374 415,865 484,865 484,876.5 484,881.908 
        508.75,858.18 508.64,858 508.688,857.82 484,834.092     "/>
</g>
<text transform="matrix(1 0 0 1 20 386.7002)" fill="#67327A" font-family="'Bungee-Regular'" font-size="34">I will not work for free</text>
</svg>

My ts for the dialog component is as follows:

import { Component } from '@angular/core';
import {MdDialog, MdDialogRef} from '@angular/material';

import { CommissionMeDialogComponent } from '../commission-me-dialog/commission-me-dialog.component';

@Component({
  selector: 'app-commission-me',
  templateUrl: './commission-me.component.html',
  styleUrls: ['./commission-me.component.css']
})

export class CommissionMeComponent {

  selectedOption: string;

  constructor(public dialog: MdDialog) {}

  openDialog() {
    let dialogRef = this.dialog.open(CommissionMeDialogComponent);
    dialogRef.afterClosed().subscribe(result => {
      this.selectedOption = result;
    });
  }
}

Upvotes: 0

Views: 3509

Answers (3)

satish ray
satish ray

Reputation: 117

Here is a very good explanation https://www.youtube.com/watch?v=Sk5jOAGl20o

What he did:

  1. Make a xyz.component.ts file without having HTML, CSS parts like this and declare it and add to entry component(check)
@Component({
  template: ''
})    

export class XyzComponent implements OnInit {
  currentDialog:MatDialogRef<any>=null;
  constructor(     private _dialog: MatDialog,private _router:Router,private 
        _arouter:ActivatedRoute
  ) {

  if(this.currentDialog){
    this.currentDialog.close();
  }
  this.currentDialog=this._dialog.open(**DialogComponent**);
  this.currentDialog.afterClosed().subscribe(res=>{
    console.log('Hello Man');
  });
}
  1. Add To your Route any route
{
  path: 'To Dialog',
  component: XyzComponent,    
},
  1. Note you can define your dialog parameters like data, height, width, etc. like before. Look at the code they are similar.

Upvotes: 0

John Crowson
John Crowson

Reputation: 83

A few strategies are discussed here (see the "Routing by Path" option):

https://medium.com/ngconf/routing-to-angular-material-dialogs-c3fb7231c177

TL;DR:

You can do it by creating a dummy component that just opens the modal on init:

@Component({
  template: ''
})
export class DialogEntryComponent {
  constructor(public dialog: MatDialog, private router: Router,
    private route: ActivatedRoute) {
    this.openDialog();
  }
  openDialog(): void {
    const dialogRef = this.dialog.open(CommissionMeDialogComponent);
    dialogRef.afterClosed().subscribe(result => {
      this.router.navigate(['../'], { relativeTo: this.route });
    });
  }
}

Then add the dummy component to your route:

RouterModule.forRoot([
    {
      path: 'home',
      component: DialogOverviewExample,
      children: [
        {
          path: 'dialog',
          component: DialogEntryComponent
        }
      ]
    }
  ])

Upvotes: 2

DeborahK
DeborahK

Reputation: 60518

You can set up your app.component.html like this:

<router-outlet></router-outlet>

With no header, menu, footer, or anything else. That way the user cannot pick anything and must focus on the currently displayed component. If you do this, then you don't technically need it to be a modal dialog.

You would then add a shell component something like this:

<pm-menu></pm-menu>

<div class='container'>
    <router-outlet></router-outlet>
</div>

You could would then route your "main" application pages to this <router-outlet> so they would have the menu, header, footer, or whatever else is on each of your pages.

The routes would look something like this:

    RouterModule.forRoot([
        { 
            path: 'wizard', 
            component: WizardComponent,
            children: [
                { path: 'page1', component: Page1Component },
                { path: 'page2', component: Page2Component },
            ]
        },
        {
            path: '',
            component: ShellComponent,
            children: [
                { path: 'welcome', component: WelcomeComponent },
                { path: 'customers', component: CustomerComponent},
                { path: '', redirectTo: 'welcome', pathMatch: 'full' },
            ]
        },
        { path: '**', component: PageNotFoundComponent }
    ])

Upvotes: 0

Related Questions