Dialog Sudut 2.0 dan Modal


128

Saya mencoba menemukan beberapa contoh tentang cara melakukan dialog modal Konfirmasi di Angular 2.0. Saya telah menggunakan dialog Bootstrap untuk Angular 1.0 dan tidak dapat menemukan contoh apa pun di web untuk Angular 2.0. Saya juga memeriksa dokumen 2.0 sudut tanpa hasil.

Apakah ada cara untuk menggunakan dialog Bootstrap dengan Angular 2.0?


Saya telah menemukan contoh ini. Mungkin itu akan membantu Anda angularscript.com/angular2-modal-window-with-bootstrap-style
Puya Sarmidani

1
Saya menggunakan yang ini dengan RC3 dan konten yang cukup dengannya: valor-software.com/ng2-bootstrap/#/modals
mentat

Berkat @Sam, saya mendapat awal yang baik. Namun, saya perhatikan bahwa komponen panggilan tidak tahu tombol mana yang diklik. Setelah beberapa penelitian, saya bisa menggunakan Observables daripada EventEmitters untuk menghasilkan solusi yang lebih elegan .
Jon


Jawaban:


199
  • Sudut 2 dan lebih tinggi
  • Bootstrap css (animasi disimpan)
  • TANPA JQuery
  • TANPA bootstrap.js
  • Mendukung konten modal khusus (seperti jawaban yang diterima)
  • Baru-baru ini menambahkan dukungan untuk beberapa modals di atas satu sama lain .

`

@Component({
  selector: 'app-component',
  template: `
  <button type="button" (click)="modal.show()">test</button>
  <app-modal #modal>
    <div class="app-modal-header">
      header
    </div>
    <div class="app-modal-body">
      Whatever content you like, form fields, anything
    </div>
    <div class="app-modal-footer">
      <button type="button" class="btn btn-default" (click)="modal.hide()">Close</button>
      <button type="button" class="btn btn-primary">Save changes</button>
    </div>
  </app-modal>
  `
})
export class AppComponent {
}

@Component({
  selector: 'app-modal',
  template: `
  <div (click)="onContainerClicked($event)" class="modal fade" tabindex="-1" [ngClass]="{'in': visibleAnimate}"
       [ngStyle]="{'display': visible ? 'block' : 'none', 'opacity': visibleAnimate ? 1 : 0}">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <ng-content select=".app-modal-header"></ng-content>
        </div>
        <div class="modal-body">
          <ng-content select=".app-modal-body"></ng-content>
        </div>
        <div class="modal-footer">
          <ng-content select=".app-modal-footer"></ng-content>
        </div>
      </div>
    </div>
  </div>
  `
})
export class ModalComponent {

  public visible = false;
  public visibleAnimate = false;

  public show(): void {
    this.visible = true;
    setTimeout(() => this.visibleAnimate = true, 100);
  }

  public hide(): void {
    this.visibleAnimate = false;
    setTimeout(() => this.visible = false, 300);
  }

  public onContainerClicked(event: MouseEvent): void {
    if ((<HTMLElement>event.target).classList.contains('modal')) {
      this.hide();
    }
  }
}

Untuk menunjukkan latar belakang , Anda akan membutuhkan sesuatu seperti CSS ini:

.modal {
  background: rgba(0,0,0,0.6);
}

Contohnya sekarang memungkinkan untuk beberapa modal secara bersamaan . (lihat onContainerClicked()metodenya).

Untuk pengguna Bootstrap 4 css , Anda perlu membuat 1 perubahan kecil (karena nama kelas css telah diperbarui dari Bootstrap 3). Baris ini: [ngClass]="{'in': visibleAnimate}"harus diubah menjadi: [ngClass]="{'show': visibleAnimate}"

Untuk menunjukkan, ini adalah sebuah plunkr


Ada gotcha sekalipun. Karena tombol-tombol tersebut dibungkus di dalam elemen tambahan di sini, gaya bootstrap tidak akan menerapkan margin pada tombol (setidaknya dalam v4). menghapus pembungkus div.modal-footerdan mengubah .app-modal-footeruntuk .modal-footermemperbaikinya.
Axel Köhler

55

Berikut adalah contoh yang cukup baik tentang bagaimana Anda dapat menggunakan modal Bootstrap dalam aplikasi Angular2 di GitHub .

Intinya adalah Anda dapat membungkus bootstrap html dan inisialisasi jquery dalam suatu komponen. Saya telah membuat modalkomponen yang dapat digunakan kembali yang memungkinkan Anda memicu pembukaan menggunakan variabel templat.

<button type="button" class="btn btn-default" (click)="modal.open()">Open me!</button>

<modal #modal>
    <modal-header [show-close]="true">
        <h4 class="modal-title">I'm a modal!</h4>
    </modal-header>
    <modal-body>
        Hello World!
    </modal-body>
    <modal-footer [show-default-buttons]="true"></modal-footer>
</modal>

Anda hanya perlu menginstal paket npm dan mendaftarkan modul modal di modul aplikasi Anda:

import { Ng2Bs3ModalModule } from 'ng2-bs3-modal/ng2-bs3-modal';

@NgModule({
    imports: [Ng2Bs3ModalModule]
})
export class MyAppModule {}

8
Nyebelin - bergantung pada jquery sebagai dependensi :(
brando

52
Ya, bootstrap bergantung padanya dan saya tidak dalam bisnis menulis ulang perpustakaan.
Douglas Ludlow

2
Ini bisa dilakukan tanpa jQuery. Saya menggunakan jawaban Sam bersama dengan tutorial di koscielniak.me/post/2016/03/angular2-confirm-dialog-component untuk menulis layanan dan komponen modal yang terkait.
BeetleJuice

Jika Anda tidak menggunakan bootstrap di proyek Anda jangan lupa untuk menambahkan tautan ke bootstrap.css. Halaman github lupa menyebutkan ini.
Shekhar

46

Ini adalah pendekatan sederhana yang tidak bergantung pada jquery atau pustaka lainnya kecuali Angular 2. Komponen di bawah ini (errorMessage.ts) dapat digunakan sebagai tampilan anak dari komponen lain. Ini hanyalah modal bootstrap yang selalu terbuka atau ditampilkan. Visibilitasnya diatur oleh pernyataan ngIf.

errorMessage.ts

import { Component } from '@angular/core';
@Component({
    selector: 'app-error-message',
    templateUrl: './app/common/errorMessage.html',
})
export class ErrorMessage
{
    private ErrorMsg: string;
    public ErrorMessageIsVisible: boolean;

    showErrorMessage(msg: string)
    {
        this.ErrorMsg = msg;
        this.ErrorMessageIsVisible = true;
    }

    hideErrorMsg()
    {
        this.ErrorMessageIsVisible = false;
    }
}

errorMessage.html

<div *ngIf="ErrorMessageIsVisible" class="modal fade show in danger" id="myModal" role="dialog">
    <div class="modal-dialog">

        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal">&times;</button>
                <h4 class="modal-title">Error</h4>
            </div>
            <div class="modal-body">
                <p>{{ErrorMsg}}</p>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" (click)="hideErrorMsg()">Close</button>
            </div>
        </div>
    </div>
</div>

Ini adalah contoh kontrol orangtua (beberapa kode yang tidak relevan telah dihapus karena singkatnya):

parent.ts

import { Component, ViewChild } from '@angular/core';
import { NgForm } from '@angular/common';
import {Router, RouteSegment, OnActivate, ROUTER_DIRECTIVES } from '@angular/router';
import { OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';


@Component({
    selector: 'app-application-detail',
    templateUrl: './app/permissions/applicationDetail.html',
    directives: [ROUTER_DIRECTIVES, ErrorMessage]  // Note ErrorMessage is a directive
})
export class ApplicationDetail implements OnActivate
{
    @ViewChild(ErrorMessage) errorMsg: ErrorMessage;  // ErrorMessage is a ViewChild



    // yada yada


    onSubmit()
    {
        let result = this.permissionsService.SaveApplication(this.Application).subscribe(x =>
        {
            x.Error = true;
            x.Message = "This is a dummy error message";

            if (x.Error) {
                this.errorMsg.showErrorMessage(x.Message);
            }
            else {
                this.router.navigate(['/applicationsIndex']);
            }
        });
    }

}

parent.html

<app-error-message></app-error-message>
// your html...

3
bagus - bisa menjelaskanclass="modal fade show in danger"
bensiu

@ Bensiu Saya menduga bahwa pemilih kelas tidak digunakan - kecuali mereka memiliki pemilih gaya css untuk semua kata-kata misalnya 'di'
Drenai

Bagaimana Anda mendapatkan efek fade in / out dengan ini?
Big McLargeHuge

10

Sekarang tersedia sebagai paket NPM

sudut-custom-modal


@Stephen Paul kelanjutan ...

  • Sudut 2 dan lebih tinggi Bootstrap css (animasi dipertahankan)
  • TANPA JQuery
  • TANPA bootstrap.js
  • Mendukung konten modal khusus
  • Dukungan untuk banyak modals di atas satu sama lain.
  • Dimodernisasi
  • Nonaktifkan gulir saat modal terbuka
  • Modal hancur ketika menavigasi.
  • Inisialisasi konten malas, yang didapat ngOnDestroy(ed) saat modal keluar.
  • Scrolling orangtua dinonaktifkan ketika modal terlihat

Inisialisasi konten malas

Mengapa?

Dalam beberapa kasus Anda mungkin tidak ingin modal untuk mempertahankan statusnya setelah ditutup, tetapi dikembalikan ke keadaan awal.

Masalah modal asli

Melewati konten secara langsung ke tampilan sebenarnya menghasilkan menginisialisasi bahkan sebelum modal mendapatkannya. Modal tidak memiliki cara untuk membunuh konten seperti itu bahkan jika menggunakan *ngIfpembungkus.

Larutan

ng-template. ng-templatetidak membuat sampai diperintahkan untuk melakukannya.

my-component.module.ts

...
imports: [
  ...
  ModalModule
]

my-component.ts

<button (click)="reuseModal.open()">Open</button>
<app-modal #reuseModal>
  <ng-template #header></ng-template>
  <ng-template #body>
    <app-my-body-component>
      <!-- This component will be created only when modal is visible and will be destroyed when it's not. -->
    </app-my-body-content>
    <ng-template #footer></ng-template>
</app-modal>

modal.component.ts

export class ModalComponent ... {
  @ContentChild('header') header: TemplateRef<any>;
  @ContentChild('body') body: TemplateRef<any>;
  @ContentChild('footer') footer: TemplateRef<any>;
 ...
}

modal.component.html

<div ... *ngIf="visible">
  ...
  <div class="modal-body">
    ng-container *ngTemplateOutlet="body"></ng-container>
  </div>

Referensi

Saya harus mengatakan bahwa itu tidak akan mungkin terjadi tanpa dokumentasi resmi dan komunitas yang bagus di internet. Mungkin membantu sebagian dari Anda juga untuk lebih memahami bagaimana ng-template, *ngTemplateOutletdan @ContentChildbekerja.

https://angular.io/api/common/NgTemplateOutlet
https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet/
https://medium.com/claritydesignsystem/ng-content -the-hidden-docs-96a29d70d11b
https://netbasal.com/understanding-viewchildren-contentchildren-and-querylist-in-angular-896b0c689f6e
https://netbasal.com/understanding-viewchildren-contentchildren-and-querylist-in- -angular-896b0c689f6e

Solusi lengkap salin-tempel

modal.component.html

<div
  (click)="onContainerClicked($event)"
  class="modal fade"
  tabindex="-1"
  [ngClass]="{'in': visibleAnimate}"
  [ngStyle]="{'display': visible ? 'block' : 'none', 'opacity': visibleAnimate ? 1 : 0}"
  *ngIf="visible">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <ng-container *ngTemplateOutlet="header"></ng-container>
        <button class="close" data-dismiss="modal" type="button" aria-label="Close" (click)="close()">×</button>
      </div>
      <div class="modal-body">
        <ng-container *ngTemplateOutlet="body"></ng-container>
      </div>
      <div class="modal-footer">
        <ng-container *ngTemplateOutlet="footer"></ng-container>
      </div>
    </div>
  </div>
</div>

modal.component.ts

/**
 * @Stephen Paul https://stackoverflow.com/a/40144809/2013580
 * @zurfyx https://stackoverflow.com/a/46949848/2013580
 */
import { Component, OnDestroy, ContentChild, TemplateRef } from '@angular/core';

@Component({
  selector: 'app-modal',
  templateUrl: 'modal.component.html',
  styleUrls: ['modal.component.scss'],
})
export class ModalComponent implements OnDestroy {
  @ContentChild('header') header: TemplateRef<any>;
  @ContentChild('body') body: TemplateRef<any>;
  @ContentChild('footer') footer: TemplateRef<any>;

  public visible = false;
  public visibleAnimate = false;

  ngOnDestroy() {
    // Prevent modal from not executing its closing actions if the user navigated away (for example,
    // through a link).
    this.close();
  }

  open(): void {
    document.body.style.overflow = 'hidden';

    this.visible = true;
    setTimeout(() => this.visibleAnimate = true, 200);
  }

  close(): void {
    document.body.style.overflow = 'auto';

    this.visibleAnimate = false;
    setTimeout(() => this.visible = false, 100);
  }

  onContainerClicked(event: MouseEvent): void {
    if ((<HTMLElement>event.target).classList.contains('modal')) {
      this.close();
    }
  }
}

modal.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { ModalComponent } from './modal.component';

@NgModule({
  imports: [
    CommonModule,
  ],
  exports: [ModalComponent],
  declarations: [ModalComponent],
  providers: [],
})
export class ModalModule { }

7

Saya menggunakan ngx-bootstrap untuk proyek saya.

Anda dapat menemukan demo di sini

Github ada di sini

Cara Penggunaan:

  1. Instal ngx-bootstrap

  2. Impor ke modul Anda

// RECOMMENDED (doesn't work with system.js)
import { ModalModule } from 'ngx-bootstrap/modal';
// or
import { ModalModule } from 'ngx-bootstrap';

@NgModule({
  imports: [ModalModule.forRoot(),...]
})
export class AppModule(){}
  1. Modal statis sederhana
<button type="button" class="btn btn-primary" (click)="staticModal.show()">Static modal</button>
<div class="modal fade" bsModal #staticModal="bs-modal" [config]="{backdrop: 'static'}"
tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sm">
   <div class="modal-content">
      <div class="modal-header">
         <h4 class="modal-title pull-left">Static modal</h4>
         <button type="button" class="close pull-right" aria-label="Close" (click)="staticModal.hide()">
         <span aria-hidden="true">&times;</span>
         </button>
      </div>
      <div class="modal-body">
         This is static modal, backdrop click will not close it.
         Click <b>&times;</b> to close modal.
      </div>
   </div>
</div>
</div>

4

Berikut ini adalah implementasi penuh saya dari komponen modalstrap bootstrap angular2:

Saya berasumsi bahwa dalam file index.html utama Anda (dengan <html>dan <body>tag) di bagian bawah <body>tag yang Anda miliki:

  <script src="assets/js/jquery-2.1.1.js"></script>
  <script src="assets/js/bootstrap.min.js"></script>

modal.component.ts:

import { Component, Input, Output, ElementRef, EventEmitter, AfterViewInit } from '@angular/core';

declare var $: any;// this is very importnant (to work this line: this.modalEl.modal('show')) - don't do this (becouse this owerride jQuery which was changed by bootstrap, included in main html-body template): let $ = require('../../../../../node_modules/jquery/dist/jquery.min.js');

@Component({
  selector: 'modal',
  templateUrl: './modal.html',
})
export class Modal implements AfterViewInit {

    @Input() title:string;
    @Input() showClose:boolean = true;
    @Output() onClose: EventEmitter<any> = new EventEmitter();

    modalEl = null;
    id: string = uniqueId('modal_');

    constructor(private _rootNode: ElementRef) {}

    open() {
        this.modalEl.modal('show');
    }

    close() {
        this.modalEl.modal('hide');
    }

    closeInternal() { // close modal when click on times button in up-right corner
        this.onClose.next(null); // emit event
        this.close();
    }

    ngAfterViewInit() {
        this.modalEl = $(this._rootNode.nativeElement).find('div.modal');
    }

    has(selector) {
        return $(this._rootNode.nativeElement).find(selector).length;
    }
}

let modal_id: number = 0;
export function uniqueId(prefix: string): string {
    return prefix + ++modal_id;
}

modal.html:

<div class="modal inmodal fade" id="{{modal_id}}" tabindex="-1" role="dialog"  aria-hidden="true" #thisModal>
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header" [ngClass]="{'hide': !(has('mhead') || title) }">
                <button *ngIf="showClose" type="button" class="close" (click)="closeInternal()"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
                <ng-content select="mhead"></ng-content>
                <h4 *ngIf='title' class="modal-title">{{ title }}</h4>
            </div>
            <div class="modal-body">
                <ng-content></ng-content>
            </div>

            <div class="modal-footer" [ngClass]="{'hide': !has('mfoot') }" >
                <ng-content select="mfoot"></ng-content>
            </div>
        </div>
    </div>
</div>

Dan contoh penggunaan dalam komponen Editor klien: client-edit-component.ts:

import { Component } from '@angular/core';
import { ClientService } from './client.service';
import { Modal } from '../common';

@Component({
  selector: 'client-edit',
  directives: [ Modal ],
  templateUrl: './client-edit.html',
  providers: [ ClientService ]
})
export class ClientEdit {

    _modal = null;

    constructor(private _ClientService: ClientService) {}

    bindModal(modal) {this._modal=modal;}

    open(client) {
        this._modal.open();
        console.log({client});
    }

    close() {
        this._modal.close();
    }

}

client-edit.html:

<modal [title]='"Some standard title"' [showClose]='true' (onClose)="close()" #editModal>{{ bindModal(editModal) }}
    <mhead>Som non-standart title</mhead>
    Some contents
    <mfoot><button calss='btn' (click)="close()">Close</button></mfoot>
</modal>

Tentu title, showClose, <mhead>dan <mfoot>ar opsional parameter / tag.


2
Alih-alih bindModal(modal) {this._modal=modal;}, Anda dapat menggunakan sudut ini ViewChildpenjelasan, seperti: @ViewChild('editModal') _modal: Modal;. Ini menangani pengikatan untuk Anda di belakang layar.
Douglas Ludlow


0

coba gunakan ng-window, itu memungkinkan pengembang untuk membuka dan mengontrol penuh beberapa jendela dalam aplikasi satu halaman dengan cara sederhana, No Jquery, No Bootstrap.

masukkan deskripsi gambar di sini

Konfigrasi yang Tersedia

  • Maksimalkan jendela
  • Minimalkan jendela
  • Ukuran khusus,
  • Posasi khusus
  • jendela bisa diseret
  • Blokir jendela induk atau tidak
  • Pusatkan jendela atau tidak
  • Berikan nilai ke jendela hasilkan
  • Lewati nilai dari jendela hasil ke jendela induk
  • Mendengarkan menutup jendela chield di jendela induk
  • Dengarkan untuk mengubah ukuran acara dengan pendengar khusus Anda
  • Buka dengan ukuran maksimal atau tidak
  • Aktifkan dan nonaktifkan pengubahan ukuran jendela
  • Aktifkan dan nonaktifkan maksimalisasi
  • Aktifkan dan nonaktifkan minimisasi

-1 Bagaimana ini berguna sama sekali? Itu tidak membahas salah satu persyaratan sebagaimana ditentukan oleh OP. Ini adalah posting ke-4 saya melihat Anda mengendalikan jawaban Anda!
avn

0

7 Sudut + NgBootstrap

Cara sederhana untuk membuka modal dari komponen utama dan meneruskan hasilnya kembali ke sana. adalah apa yang saya inginkan. Saya membuat tutorial langkah-demi-langkah yang mencakup membuat proyek baru dari awal, menginstal ngbootstrap dan pembuatan Modal. Anda dapat mengkloningnya atau mengikuti panduan ini.

Semoga ini bisa membantu baru untuk Angular.!

https://github.com/wkaczurba/modal-demo

Detail:

template modal-simple (modal-simple.component.html):

<ng-template #content let-modal>
  <div class="modal-header">
    <h4 class="modal-title" id="modal-basic-title">Are you sure?</h4>
    <button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
  <div class="modal-body">
    <p>You have not finished reading my code. Are you sure you want to close?</p>
  </div>
  <div class="modal-footer">
    <button type="button" class="btn btn-outline-dark" (click)="modal.close('yes')">Yes</button>
    <button type="button" class="btn btn-outline-dark" (click)="modal.close('no')">No</button>
  </div>
</ng-template>

Modal-simple.component.ts:

import { Component, OnInit, ViewChild, Output, EventEmitter } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';

@Component({
  selector: 'app-modal-simple',
  templateUrl: './modal-simple.component.html',
  styleUrls: ['./modal-simple.component.css']
})
export class ModalSimpleComponent implements OnInit {
  @ViewChild('content') content;
  @Output() result : EventEmitter<string> = new EventEmitter();

  constructor(private modalService : NgbModal) { }

  open() {
    this.modalService.open(this.content, {ariaLabelledBy: 'modal-simple-title'})
      .result.then((result) => { console.log(result as string); this.result.emit(result) }, 
        (reason) => { console.log(reason as string); this.result.emit(reason) })
  }

  ngOnInit() {
  }

}

Demo itu (app.component.html) - cara sederhana untuk menangani acara pengembalian:

<app-modal-simple #mymodal (result)="onModalClose($event)"></app-modal-simple>
<button (click)="mymodal.open()">Open modal</button>

<p>
Result is {{ modalCloseResult }}
</p>

app.component.ts - onModalClosed dieksekusi setelah modal ditutup:

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  modalCloseResult : string;
  title = 'modal-demo';

  onModalClose(reason : string) {
    this.modalCloseResult = reason;
  }    
}

Bersulang

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.