Динамические компоненты


Динамические компоненты создаются уже в скомпилированном приложении в момент его работы.

В Angular динамическая компиляция компонентов реализована через сервис ComponentFactoryResolver.

Для отображения такого компонента сперва необходимо определить место, где он будет располагаться. Местом служит ссылка на представление типа ViewContainerRef.

books-list.component.html


<div>
<div class="book-item" #book>
<p>No books</p>
</div>

<button (click)="addBook()">Add book</button>
</div>
books-list.component.ts


@Component({
selector: 'books-list',
templateUrl: './books-list.component.html',
})
export class AppComponent {
@ViewChild('book') book

constructor(
private componentFactoryResolver: ComponentFactoryResolver
) {}

addBook() {
this.book.viewContainerRef.clear()

let bookItemComponent = this.componentFactoryResolver.resolveComponentFactory(
BookItemComponent
)
let bookItemComponentRef = this.book.viewContainerRef.createComponent(
bookItemComponent
)
;(<BookItemComponent>(
bookItemComponentRef.instance
)).value = {
title: 'Great Expectations',
author: 'Charles Dickens',
}
}
}
book-item.component.html


<div class="book-item">
<div>Title: {{value?.title}}</div>
<div>Author: {{value?.author}}</div>
</div>
book-item.component.ts


@Component({
selector: 'book-item',
templateUrl: './book-item.component.html',
})
export class BookItemComponent {
value: any = null
constructor() {}
}
Вызов метода clear() у viewContainerRef очищает содержимое блока представления.

Метод resolveComponentFactory() сервиса ComponentFactoryResolver принимает определение класса нужного динамического компонента и возвращает его экземпляр в виде ссылки типа ComponentRef. Для добавления созданного экземпляра в шаблон необходимо передать его в качестве параметра методу createComponent() экземпляра класса ViewContainerRef.

Метод createComponent() возвращает ссылку на созданный компонент, с помощью которой можно манипулировать значениями свойств компонента и вызывать его методы.

Все динамические компоненты (Angular dynamic component) должны перечисляться в свойстве entryComponents того модуля, к которому они относятся.

Стоит отметить, что невозможно создать компонент только в контроллере без представления. В шаблоне всегда должно быть предусмотрено для него место. Если не хочется плодить лишние HTML-теги - используйте Angular элемент <ng-template />.


<div>
<button (click)="addBook()">Add book</button>

<ng-template #book></ng-template>
</div>