Cómo crear una ventana emergente modal compatible con Angular 4

Quiero ser capaz de crear una ventana emergente que cargará un determinado componente Angular 4 mío cuando se selecciona un botón de radio.

Parece que los métodos que aparecen en las respuestas a esta pregunta solo son compatibles con Angular 2.

No sé por dónde empezar y agradecería cualquier ayuda.

La respuesta aceptada añade una gran dependencia para matar una mosca. Los diálogos modales (y sin modelo) son en gran parte el resultado de una clase CSS o dos. Pruebe este "renombrar..." ejemplo:

  1. Escriba el padre y el hijo-modal como si el hijo no fuera modal en absoluto, sino sólo un formulario en línea con *ngIf adjunto.

HTML padre que utiliza `` hijo:

<div>
    A div for {{name}}.
    Rename

</div>

Clase padre. El decorador @Component omitido por brevedad. (La propiedad name pertenece a la clase padre y existiría aunque no tuviéramos un formulario para modificarla).

export class AppComponent {
    name = "old name";

    showIt = false;
    showModal() {
        this.showIt = true;
    }
    closeModal(newName: string) {
        this.showIt = false;
        if (newName) this.name = newName;
    }

}

Componente hijo a modalizar. Decorador @Component e importaciones omitidas de nuevo.

export class MyModalComponent {
    @Input() oldname = "";
    @Output() close = new EventEmitter();
    newname = "";

    ngOnInit() {
        // copy all inputs to avoid polluting them
        this.newname = this.oldname; 
    }

    ok() {
        this.close.emit(this.newname);
    }

    cancel() {
        this.close.emit(null);
    }
}

HTML hijo antes de modalizarlo.

<div>
    Rename {{oldname}}
    <input type="text" (change)="newname = $event.target.value;" />
    OK
    Cancel
</div>
  1. Aquí está el CSS para el niño, pero se puede colocar en una hoja de estilos global para su reutilización en toda la aplicación. Es una única clase llamada modal y está pensada para un elemento <div>.
.modal {
    /* detach from rest of the document */
    position: fixed;

    /* center */
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);

    /* ensure in front of rest of page -- increase as needed */
    z-index: 1001;

    /* visual illusion of being in front -- alter to taste */
    box-shadow: rgba(0,0,0,0.4) 10px 10px 4px;

    /* visual illusion of being a solid object -- alter to taste */
    background-color: lightblue;
    border: 5px solid darkblue;

    /* visual preference of don't crowd the contents -- alter to taste */
    padding: 10px;
}

Pero la clase CSS modal no impide interactuar con la página que hay debajo. (Así que colocamos un overlay debajo del modal para absorber e ignorar la actividad del ratón. overlay también está pensado para un elemento <div>.

.overlay {
    /* detach from document */
    position: fixed;

    /* ensure in front of rest of page except modal */
    z-index: 1000;

    /* fill screen to catch mice */
    top: 0;
    left: 0;
    width: 9999px;
    height: 9999px;

    /* dim screen 20% -- alter to taste */
    opacity: 0.2;
    background-color: black;
}
  1. Usa el modal y el overlay en el HTML hijo.
<div class="modal">
    Rename {{oldname}}
    <input type="text" (change)="newname = $event.target.value;" />
    OK
    Cancel
</div>
<div class="overlay"></div>

Y eso'es todo. Básicamente 2 clases CSS y puedes hacer de cualquier componente un modal. De hecho puedes mostrar un componente en línea o como modal en tiempo de ejecución simplemente alterando la existencia de la clase CSS con ngClass o [class.modal]="showAsModalBoolean".

Puedes alterar esto para que el hijo controle la lógica de mostrar/ocultar. Mueve las funciones *ngIf, showIt, y show() al hijo. En el padre añade @ViewChild(MyModalComponent) renameModal: MyModalComponent; y entonces el padre puede imperativamente llamar a this.renameModal.show(this.name); y re-cablear la inicialización y los divs contenedores como sea necesario.

El módulo hijo puede devolver información a una función padre como se muestra arriba, o el método show() del módulo hijo puede aceptar una llamada de retorno o devolver una Promise, según se prefiera.

Dos cosas que hay que saber:

this.renameModal.show(..); no funcionará si hay un ngIf en `` porque para empezar no existirá para exponer la función. ngIf elimina todo el componente, función show() y todo, así que usa [hidden] en su lugar si necesitas esto por alguna razón.

Modals-on-modals tendrán problemas de z-index ya que todos comparten el mismo z-index. Esto puede resolverse con `[style.z-index]="calculatedValue"o similar.

Comentarios (4)
Solución

Compruebe Angular Material Dialogue, aquí está el Plunker

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

@Component({
  selector: 'dialog-result-example',
  templateUrl: './dialog-result-example.html',
})
export class DialogResultExample {
  selectedOption: string;

  constructor(public dialog: MdDialog) {}

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

@Component({
  selector: 'dialog-result-example-dialog',
  templateUrl: './dialog-result-example-dialog.html',
})
export class DialogResultExampleDialog {
  constructor(public dialogRef: MdDialogRef) {}
}
Comentarios (9)