Упрощение создания приложения с помощью динамических компонентов в Angular 6

Упрощение создания приложения с помощью динамических компонентов в Angular 6

От автора: динамические компоненты в любом фреймворке/библиотеке упрощают в Angular создание приложения больших масштабов. Давайте посмотрим, как мы можем создавать динамические компоненты в Angular 6.

Начало работы с Angular

Во-первых, создайте новый Angular проект. Если в вашей системе не установлен Angular, или если вы все еще используете старую версию Angular, выполните следующую команду на своем терминале:

$ npm install -g @ angular / cli 

Ради этого поста я создал простое приложение с Angular выражением. Клонируйте его в свою систему.

$ git clone https://github.com/rajatgeekyants/hero.git
$ cd hero
$ yarn install
$ ng serve --open

Это запустит приложение, а флаг —open автоматически откроет браузер по http://localhost:4200/.

Создание шаблона в шаблоне

Angular поставляется с компонентом ng-template который позволяет нам объявлять любую часть шаблона Angular. Это отличный способ придавать нашему шаблону динамичность, предоставляя нам возможность использовать наш код и передавать его другим компонентам.

В файле app.component.ts напишите новый компонент ng-template в конце template.

<ng-template #hello> Hello, World
</ng-template>

Если вы сейчас откроете приложение, вы увидите, что новый текст приложения не отображается. Это потому, что вещи, которые находятся внутри компонента ng-template можно только захватить и использовать где-то еще позже.

Чтобы иметь возможность захватить этот шаблон, я дал ему переменную hello. Теперь перейдите в код Component этого файла и добавьте переменную hello внутри ViewChild. Импортируйте ViewChild из @angular/core.

export class AppComponent implements OnInit, AfterViewInit { @ViewChild('hello') helloTemplate; heroes;
}

Теперь нам нужно иметь доступ к коду, который захвачен ViewChild. Для этого мы будем использовать хук жизненного цикла AfterViewInit. Убедитесь, что вы импортируете AfterViewInit из @angular/core. Напишите следующий код внутри Component:

ngAfterViewInit() { console.log(this.helloTemplate);
}

Откройте инструменты разработчика. Вы заметите, что там есть TemplateRef, в котором есть несколько свойств. Мы рассмотрим их позже.

Передача ссылки шаблона компоненту

Если вы посмотрите файл tab.component.ts, вы увидите, что он использует компонент ng-content для рендеринга контента, предоставленного разработчиком. Давайте посмотрим, как мы можем сделать одну из вкладок для отображения переменной hello, которую мы определили ранее, используя ng-template и визуализировать ее с помощью ng-container и ngTemplateOutlet.

Сначала удалите текст, который передается на вкладке Hero. Мы хотим, чтобы эта вкладка отображала text внутри переменной hello.

<ngx-tab tabTitle="Hero" [template]="hello"></ngx-tab>

Затем перейдите в файл tab.component.ts и объявите template как входной TabComponent внутри TabComponent:

export class TabComponent { @Input() tabTitle: string; @Input() active = false; @Input() template; // new line
}

Внутри @Component у нас есть компонент ng-content, который ничего не делает. Добавьте к компоненту ng-content условие, согласно которому ng-content должен отображать пустое пространство, если нет template.

 <ng-content * ngIf = "! template"> </ ng-content> 

Ниже этой строки создайте компонент ng-container, который будет отображать template.

 <ng-container * ngIf = "template" [ngTemplateOutlet] = "template"> </ ng-container> 

Обновите свой браузер, и вы увидите, что вторая вкладка отображает переменную hello.

Передача данных в динамический ng-template

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

Сначала перейдите в файл tab.component.ts и добавьте новый Input() внутри задачи TabComponent. Этот Input() будет проходить через данные извне.

export class TabComponent { @Input() tabTitle: string; @Input() active = false; @Input() template; @Input() dataContext;
}

Теперь нам нужно передать эти данные в наш шаблон. Это делается с использованием свойства ngtemplateOutletContext в компоненте ng-container.

<ng-container *ngIf="template" [ngTemplateOutlet]="template" [ngTemplateOutletContext]="{data: dataContext}"
></ng-container>

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

Теперь перейдите в файл app.component.ts и используйте dataContext во втором компоненте ngx-tab.

<ngx-tab tabTitle="Hero" [template]="hello" [dataContext="heroes[0]"]
></ngx-tab>

У нас есть только одна запись внутри массива heroes. Эти данные передаются, а затем внутри компонента ngx-tab мы передадим его нашему шаблону, который в этом случае находится здесь.

Теперь мы можем использовать этот объект данных и использовать его внутри нашего компонента. Я хочу визуализировать имя этого человека, поэтому я бы сделал что-то вроде hero?.name. ? размещается здесь, если hero не определен. Нам также необходимо определить hero как data.

<ng-template #hello let-hero="data"> Hello, {{hero?.name}}
</ng-template>

Как только ваш браузер обновится, перейдите на вторую вкладку, и вы увидите, что имя правильно отображается.

Якорная точка

При динамическом создании компонента мы должны знать, где разместить компонент в шаблоне другого компонента.

Чтобы сделать это, мы можем использовать пользовательскую директиву, которая выставляет ViewContainerRef и служит нам в качестве точки привязки, которую мы можем ссылаться в дальнейшем.

Сначала перейдите на tabs.component.ts и создайте новый компонент ng-template внутри ng-template @Component.

 <ng-template appDynamicTabAnchor> </ ng-template> 

Это область, в которой мы собираемся ввести динамические компоненты позже. Во-первых, нам нужно иметь возможность ссылаться на компонент ng-template. Нам также нужен доступ к ViewContainerRef, который позволит нам динамически создавать компоненты.

Используйте Angular CLI и создайте новую директиву, которая будет служить нам в качестве точки привязки:

$ ng gd tabs / dynamicTabAnchor --flat --spec false 

Это создаст новый файл внутри папки tabs именем dynamic-tab-anchor.directive.ts. Напишите в нем следующий код:

import { Directive, ViewContainerRef } from '@angular/core';
@Directive({ selector: '[appDynamicTabAnchor]'
})
export class DynamicTabAnchorDirective { constructor(public viewContainer: ViewContainerRef) { }
}

Нам также нужно импортировать этот файл в файл tabs.component.ts.

import {DynamicTabAnchorDirective} from './dynamic-tab-anchor.directive.ts';

Теперь мы можем использовать @ViewChild внутри класса TabsComponent и захватить все экземпляры директив динамической привязки вкладок внутри dynamicTabPlaceholder.

@ViewChild(DynamicTabAnchorDirective) dynamicTabPlaceholder; DynamicTabAnchorDirective

Теперь мы можем создать метод openTab. Затем этот метод будет вызван извне. Я залогирую ViewContainerRef.

openTab() { console.log(this.dynamicTabPlaceholder.viewContainer)
}

Перейдите в файл app.components.ts и подключите метод openTab к компоненту app-heroes-list:

 <app-heroes-list [heroes] = "heroes" (addPerson) = "onAddPerson ()"> </ app-heroes-list> 

Мы должны реализовать это в классе AppComponent. Здесь мы будем называть функцию openTab, которую мы создали внутри tabComponent.

onAddPerson() { this.tabsComponent.openTab();
}

Теперь, если вы нажмете кнопку «Add new button», вы увидите, что ViewContainerRef распечатан в DevTools.

Заключение

Динамические компоненты являются многоразовыми и упрощают создание крупномасштабных приложений. Этот пост является всего лишь шагом вперед для обеспечения динамичности для компонентов Angular.

Я надеюсь, что этот пост помог вам лучше разобраться в динамичности в Angular. Следите за новыми постами в Angluar, Vue, React и других популярных фреймворках/библиотеках.

Автор: Rajat S

Источник: https://blog.bitsrc.io/

Редакция: Команда webformyself.