Лучший способ добавить угловой компонент в событие RunTime On Click

Веб-сайт, который я создаю, состоит из нескольких компонентов. В компоненте «Домашняя страница», когда пользователь нажимает кнопку, чтобы добавить что-то на страницу, я хочу добавить компонент по своему выбору к «домашнему» компоненту. Я исследовал и нашел 3 способа сделать это, но я хочу знать, что лучше всего использовать для такой функции. Страница будет инициализирована с некоторыми компонентами, уже добавленными другими пользователями. Я хочу, чтобы пользователи могли добавлять туда компоненты.

Angular говорит, что я должен сделать это следующим образом: https://angular.io/guide/dynamic-component-loader

Angular Material говорит, что я должен сделать это следующим образом: https://material.angular.io/cdk/portal/overview

И я лично ожидал этого (который работает), но я не думаю, что это "лучшая практика":

Поэтому, когда пользователь нажимает на этот тег, он запускает метод добавления:

<a class="dropdown-item" href="#!" (click)="prependMedia('elementOne')">ElementOne</a>

Этот метод вызывает это в файле TS компонента, эффективно проталкивая новый элемент в массив. Затем указанный HTML-код будет следить за добавлением нового элемента и помещать компонент в ngFor:

Файл TypeScript:

mediaElements: any[] = [];
  element: any = {
    name: 'elementOne',
    data: 'data'
};

constructor() { }

ngOnInit() {}

prependMedia(type: string) {
 console.log(type);
 this.mediaElements.push(this.element);
}

HTML-файл, который добавит компонент после добавления новой модели для него в массив mediaElements:

<div *ngFor="let element of mediaElements" [(ngModel)]="mediaElements">
  <div *ngIf="element.name == 'elementOne'">
    <app-elementone></app-elementone>
  </div>
</div>

Мой вопрос: что не так с методом, который я использую с ngFor? Не самоуверенно, а технически. Каков наилучший способ добавления компонента в DOM, когда пользователь нажимает кнопку, чтобы добавить его на страницу? И почему? Не самоуверенным образом, а технически или с доказательствами от команды Angular.

Изначально я собирался использовать то, что я показал в коде, но теперь я нашел и метод Angular, и способ Angular Material, и я ищу факты о том, как лучше всего.

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

Дайте мне знать, если вам понадобится дальнейшее описание.

Спасибо, Эрик


person Eric Belisle Giddings    schedule 18.08.2019    source источник
comment
что цикл for, на мой взгляд, самый простой способ сделать это, единственный случай, когда он не сработает, вероятно, если вы не знаете, какие компоненты могут использоваться пользователем, тогда вам нужно будет использовать решение с динамическими компонентами   -  person Xesenix    schedule 18.08.2019
comment
@Xesenix Я думаю, что часть моей проблемы связана с тем, что, я согласен, это самый простой способ, но есть ли какая-то причина, которая делает это плохой практикой? Должна быть причина, по которой Angular и Angular Material создали свои методы, а не то, что я написал. Я знаю типы каждого элемента, который они будут добавлять (например, у меня есть модель для каждого динамического компонента, и есть только установленные типы, которые они могут добавить)   -  person Eric Belisle Giddings    schedule 18.08.2019
comment
По своему опыту могу сказать, что примерно через 1,5–2 года использования этого простого решения я не увидел ничего, что могло бы сделать его антипаттерном, кроме связывания визуализированных компонентов с модулем, который их отображает. Так что это зависит от того, насколько широко вам нужно использовать этот шаблон. Если бы только в нескольких местах я бы сказал, что дополнительная работа по обработке динамических компонентов не стоит того, в другом случае, когда вы, например, создаете повторно используемый компонент, который может использовать компоненты, которые не известны в контексте цикла рендеринга, идут с динамическими компонентами.   -  person Xesenix    schedule 18.08.2019


Ответы (1)


Синтаксис *ngFor, который вы используете, является стандартным подходом

Динамические компоненты больше подходят для ситуаций, когда вы не знаете, какие компоненты вам могут потребоваться. Примером этого является модальный диалог, в котором модальное окно может отображать компоненты любого типа - или если у вас есть сторонняя библиотека, которая отображает компоненты, переданные пользователем библиотеки.

Если вам не нужен внешний div, вы можете использовать:

<ng-container *ngFor="let element of mediaElements">

</ng-container>

Если у вас <div *ngIf="element.name == 'elementOne'">, вы можете использовать *ngSwitch, где регистр переключателя будет именем элемента - это подойдет, если бы вам нужно было отобразить несколько разных компонентов. На сайте Angular Docs есть хороший пример ngSwitch, который довольно близок к тому, что ты делаешь (насколько я могу судить)

Примечание. Я не уверен, зачем вам ngModel привязка. Лучше отправлять события из шаблона и обновлять привязки в компоненте.

person Drenai    schedule 18.08.2019
comment
Спасибо за развернутый ответ! Также для указания на переключатель было бы гораздо лучшим способом справиться с этим ... также для информации ngModel ... Я отметил это как правильный ответ, потому что он точно описывает то, что мне нужно знать ... Мне интересно почему теперь есть разница между Angular Material Portals и Angular's Dynamic Component docs. Это просто любопытство, хотя это очень помогло. Спасибо! - person Eric Belisle Giddings; 19.08.2019
comment
Разница между документами портала CDK и документами динамических компонентов заключается в том, что CDK является необязательной библиотекой. Он добавляет оболочки для функций Angular, таких как динамические компоненты, чтобы упростить их использование. - person Drenai; 19.08.2019
comment
спасибо за это различие. Я знал, что CDK необязателен, поскольку он является частью Angular Material. Я не знал, что порталы - это оболочка для функциональности динамических компонентов. - person Eric Belisle Giddings; 20.08.2019