用服务创建Angular 7模态对话框/弹出窗口

4
我刚接触Angular,有关服务有一个问题。在以前的其他语言中,我会创建自包含的组件,可以从应用程序的任何地方调用。
我需要弹出对话框和错误消息,这些消息显示为模态,可以从不同的服务或组件的ts文件中调用。
我的最终目标是不要在多个组件中使用对话框的HTML,而是在单个服务或组件和服务中使用。
我的初步想法是创建一个服务,其中包含模板和样式部分(如果这些在服务中可用),它是完全自包含的;如果这不可行,则创建一个包含标记和样式的单独组件和具有对话框方法的服务。
我的想法是以下两种之一: 1. 一个服务,其中包含必要的HTML、样式和显示对话框或错误消息的方法。 2. 一个服务和组件配合使用来显示对话框。
我这样考虑正确吗?还是我在考虑做某些事情时会遇到麻烦?

使用Angular Material MatDialog,您可以将其扩展并将其用作其他组件之间的服务,您可以在其网站上找到更多示例。https://material.angular.io/components/dialog/overview - ramon22
1个回答

3
使用服务来封装Angular对话框逻辑是一个很好的方法。利用Angular Material Dialog,您可以创建以下服务。

DialogService

最初的回答
import { ElementRef, Injectable } from '@angular/core'
import { MatDialog, MatDialogRef } from '@angular/material'
    
import { DialogProfileOptionsComponent } from './dialog-profile-options/dialog-profile-options.component'
import { DialogYesNoComponent } from './dialog-yes-no/dialog-yes-no.component'
    
    
@Injectable({
  providedIn: 'root'
})
export class DialogService {
    
  constructor(public dialog: MatDialog) { }
    
  public open_info_dialog() { }
    
  public open_profile_options_dialog(
    { 
      position_relative_to_element, 
      user,
      has_backdrop = false, 
      height = '135px', 
      width = '290px' 
    }: {
      position_relative_to_element: ElementRef, 
      user: firebase.User, 
      has_backdrop?: boolean,
      height?: string, 
      width?: string
    }
  ): MatDialogRef<DialogProfileOptionsComponent> {
    const dialog_ref: MatDialogRef<DialogProfileOptionsComponent> =
      this.dialog.open(DialogProfileOptionsComponent, {
        hasBackdrop: has_backdrop,
        height: height,
        width: width,
        data: { position_relative_to_element: position_relative_to_element, user: user }
      });
    return dialog_ref;
  }
    
  public open_yes_no_dialog(
    { 
      question, 
      title = 'Confirm', 
      yes_button_first = true,
      has_backdrop = false, 
      height = '250px', 
      width = '350px' 
    }: {
      question: string, 
      title?: string, 
      yes_button_first?: boolean, 
      has_backdrop?: boolean,
      height?: string, width?: string
    }
  ): MatDialogRef<DialogYesNoComponent> {  
    const dialog_ref = this.dialog.open(DialogYesNoComponent, {
      autoFocus: true,
      backdropClass: 'cdk-overlay-transparent-backdrop',
      closeOnNavigation: true,
      disableClose: false,
      hasBackdrop: has_backdrop,
      height: height,
      width: width,
      data: { question: question, title: title, yes_button_first: yes_button_first }
    });
    
    return dialog_ref;
  }
    
  open_warning_dialog() { /* TODO  */ }
}

dialog-profile-options.component.ts

import { Component, ElementRef, Inject, OnInit } from '@angular/core'
import { MatDialogConfig, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'
    
    
@Component({
  selector: 'dialog-profile-options',
  templateUrl: './dialog-profile-options.component.html',
  styleUrls: ['./dialog-profile-options.component.css']
})
export class DialogProfileOptionsComponent implements OnInit {
  private position_relative_to_element: ElementRef
    
  constructor(
    public dialog_ref: MatDialogRef<DialogProfileOptionsComponent>,
    @Inject(MAT_DIALOG_DATA) public options: { 
      position_relative_to_element: ElementRef,
      user: firebase.User 
    }
  ) {  
    this.position_relative_to_element = options.position_relative_to_element
  }
    
  ngOnInit() {
    const mat_dialog_config = new MatDialogConfig()
    const rect: DOMRect = this.position_relative_to_element.nativeElement.getBoundingClientRect()
    
    mat_dialog_config.position = { right: `10px`, top: `${rect.bottom + 2}px` }
    this.dialog_ref.updatePosition(mat_dialog_config.position)
  }
    
}

dialog-profile-options.component.html

<div mat-dialog-content>
  <div><b>{{options.user.displayName}}</b></div>
  <div class="text-secondary">{{options.user.email}}</div>
</div>
<div mat-dialog-actions>
  <button mat-button mat-dialog-close="view-profile" cdkFocusInitial>View profile</button>
  <button mat-button mat-dialog-close="sign-out">Sign out</button>
</div>

@Christoper,谢谢,我正在尝试避免使用PrimeNG或Material等其他依赖项,但我认为我可以利用你发布的内容,并将其与html/css模板和服务一起使用。 - Eric B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接