Как вызвать один и тот же угловой компонент несколько раз с помощью querySelector

Итак, у меня есть компонент под названием custom-modal.component. HTML-файл выглядит следующим образом:

<dialog id = "custom-modal">
 <ng-content></ng-content>
</dialog>

В файле .ts у меня есть

this.modal = document.querySelector('#modal-custom');

// Buttons listeners to showModal() and close() methods...

Проблема возникает, если я пытаюсь вызвать modal несколько раз:

<button class = "open-modal">See cards</button>
<button class = "open-modal">See flowers</button>

<app-custom-modal>
  <app-cards></app-cards>
</app-custom-modal>

<app-custom-modal>
  <app-flowers></app-flowers>
</app-custom-modal>

Итак, в Angular это будет выглядеть так:

<button class = "open-modal">See cards</button>
<button class = "open-modal">See flowers</button>

*** NOTE that there's two ***

<dialog id = "custom-modal">
 <div> <h1> Cards title </h1> </div>
</dialog>

<dialog id = "custom-modal">
 <div> <h1> Flowers title </h1> </div>
</dialog>

querySelector не будет работать, так как он выбирает только первый. Я могу сделать querySelectorAll и перебрать все модальные окна, но тогда у меня нет способа назначить прослушиватель кнопок для отображения правильного модального окна (или я не знаю, как это сделать).

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

🤔 А знаете ли вы, что...
С помощью JavaScript можно создавать клиентские приложения для мобильных устройств с использованием фреймворков, таких как React Native и NativeScript.


1
43
1

Ответ:

Решено

Важно помнить, где вы хотите обрабатывать открытое/закрытое состояние вашего диалога.

В этом случае вы делаете это в компоненте, в котором находится модальное окно. Что вы можете сделать, так это передать ввод, скажем, видимый, модальному, который указывает открытое/закрытое состояние. Вы также можете определить вывод, который уведомляет вас, если модальное окно получило команду закрыться из модального компонента.

Я также рекомендую вам использовать ViewChild в модальном компоненте вместо document.querySelector(...). Обратите внимание, что при использовании ViewChild вам, скорее всего, придется использовать хук жизненного цикла AfterViewInit.

.ts файл CustomModalComponent

import { Component, OnInit, AfterViewInit, ViewChild, ElementRef, Input, Output, EventEmitter } from '@angular/core';
// ... the rest of import

@Component({
  // ... Component decorator props (selector, templateUrl, styleUrls)
})
export class CustomModalComponent implements OnInit, AfterViewInit {
  @ViewChild('modalRef') modalRef: ElementRef;
  @Input() visible: boolean;
  
  // Optional if you want to close the dialog from here and notify the parent (host)
  @Output() closed = new EventEmitter(); 

  constructor() { }

  ngAfterViewInit(): void {
    // Print the HTMLElement of the modal
    console.info(this.modalRef.nativeElement);

    // Do your thing
  }

  close() {
    this.closed.emit();
    // ...
  }

  // ... the rest of the component
}

.html CustomModalComponent

<dialog #modalRef>
 <ng-content></ng-content>
</dialog>

Затем, когда вы хотите использовать его в ParentComponent

В вашем .html

<button class = "open-modal" (click) = "openCards()">See cards</button>
<button class = "open-modal" (click) = "openFlowers()">See flowers</button>

<app-custom-modal [visible] = "visibleCards" (closed) = "closeCards()">
  <app-cards></app-cards>
</app-custom-modal>

<app-custom-modal [visible] = "visibleFlowers" (closed) = "closeFlowers()">
  <app-flowers></app-flowers>
</app-custom-modal>

В вашем .ts

import { Component } from '@angular/core';
// ... the rest of import

@Component({
  // ... Component decorator props (selector, templateUrl, styleUrls)
})
export class ParentComponent {
  visibleCards: boolean;
  visibleFlowers: boolean;

  constructor() { }

  openCards() {
    this.visibleCards = true;
    // ...
  }

  openFlowers() {
    this.visibleFlowers = true;
    // ...
  }

  closeCards() {
    this.visibleCards = false;
    // ...
  }

  closeFlowers() {
    this.visibleFlowers = false;
    // ...
  }

  // ... the rest of the component
}