Angular에서 동적으로 구성 요소 생성
흥미로운 점 중 하나는 중요한 기술이지만 실제로는 필요하지 않은 Angular의 Reactive Forms에 사로잡힐 수 있다는 것입니다. 내가 할 수 있기를 원했던 것은 구성 요소에서 레이아웃을 만드는 것이었습니다. 그리 어렵지 않은 것으로 나타났습니다.
나는 새로운 Angular 프로젝트로 시작했습니다. 완료율이 있는 막대를 표시하기 위해 간단한 작은 구성 요소를 만들었습니다(정말 간단함).
import { Component } from "@angular/core";
@Component({
template: `<div class="border rounded border-gray-300 m-1 p-1">
<div>% Complete</div>
<div [innerHtml]="'█'.repeat(this.val)"></div>
</div>`
})
export class Gauge {
val = 0;
}
이 중 하나는 다음과 같습니다.
동적으로 여러 개를 만들 수 있기를 원했습니다. 두 가지가 필요했습니다.
컨테이너 가져오기
템플릿의 최상위 컨테이너에 액세스하려는 경우 ViewContainerRef 객체를 생성자에 주입하면 됩니다.
@Component({
selector: 'app-root',
template: `
<div class="container mx-auto bg-white">
<div class="text-xl">Dashboard</div>
<div class="grid grid-cols-4">
</div>
</div>
`,
styles: []
})
export class AppComponent implements OnDestroy {
components: Array<ComponentRef<Gauge>> = [];
constructor(private ViewContainerRef container) { }
이 접근 방식의 문제는 내가 최상위 컨테이너를 원하지 않고 마크업 내부에 추가로 삽입하고 싶었다는 것입니다. 그리드 div에 주입하고 싶었습니다. 이를 위해 div 내부에 ng-template을 추가했습니다.
<div class="container mx-auto bg-white">
<div class="text-xl">Dashboard</div>
<div class="grid grid-cols-4">
<ng-template #gauges ></ng-template>
</div>
</div>
컨테이너를 잡을 수 있도록 #gauges를 사용하여 컨테이너 이름을 지정했습니다. @ViewChild 데코레이터로 이 작업을 수행했습니다.
@ViewChild("gauges", { read: ViewContainerRef }) container: ViewContainerRef;
이것은 컨테이너 멤버를 ViewContainerRef(위의 생성자 주입처럼)로 연결하지만 이 특정 요소에 대해 연결합니다. 이것이 연결되려면 보기가 초기화될 때까지 기다려야 합니다.
ngAfterViewInit(): void {
// container is now valid, ngOnInit is too early
}
이제 컨테이너가 생겼습니다. 새 게이지 구성 요소를 생성하려면 어떻게 해야 합니까?
컴포넌트 팩토리 얻기
게이지를 생성할 수 있는 팩토리를 얻으려면 생성자에 주입할 수 있는 팩토리 리졸버가 필요합니다.
constructor(private resolver: ComponentFactoryResolver) { }
이 리졸버를 사용하여 컴포넌트의 팩토리를 확인할 수 있습니다.
// Get a factory for a known component
const factory: ComponentFactory<Gauge> =
this.resolver.resolveComponentFactory(Gauge);
이는 컴포넌트를 생성하는 데 사용할 수 있는 팩토리를 제공합니다. 그런 다음 동적으로 여러 개를 만들 수 있습니다.
// Dynamic creating them
for (let x = 0; x < 20; ++x) {
this.container.createComponent(factory);
}
createComponent를 호출하면 컨테이너에 삽입됩니다. 이것은 팩터리를 허용하는 컨테이너의 메서드입니다. 문제가 없는지 확인하려면 onDestroy로 제거할 수 있도록 구성 요소에 대한 핸들을 유지해야 합니다.
// Dynamic creating them
for (let x = 0; x < 20; ++x) {
const gauge = this.container.createComponent(factory);
// Keep a copy for destruction
this.myGauges.push(gauge);
}
그런 다음 그냥 파괴하십시오.
ngOnDestroy(): void {
for (let x = 0; x < this.myGauges.length; ++x) {
this.myGauges[x].destroy();
}
}
이것은 잘 작동하지만 일부 상태를 설정해야 하는 경우에는 어떻게 해야 합니까? 게이지에는 백분율을 표시하는 val 속성이 있음을 기억하십시오. 이를 위해 인스턴스를 확인하여 게이지 자체에 속성을 설정할 수 있습니다(여기서 반환된 게이지는 구성 요소에 대한 참조일 뿐임을 기억하십시오).
// Dynamic creating them
for (let x = 0; x < 20; ++x) {
const gauge = this.container.createComponent(factory);
// Set instance properties
gauge.instance.val = Math.ceil(Math.random() * Math.floor(20));
// Ensure that change detection happens once
gauge.changeDetectorRef.detectChanges();
// Keep a copy for destruction
this.myGauges.push(gauge);
}
이 경우 각 게이지에 임의의 숫자를 설정합니다. 그러나 구성 요소에 의해 생성된 후 상태를 변경하는 경우 변경 내용을 연결하도록 changeDetector에 지시해야 합니다. 해당 줄이 없으면 변경 감지의 일관성을 얻습니다.
그게 다야.
여기에서 전체 코드를 얻을 수 있습니다.
Shawn Wildermuth의 이 저작물은 Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License에 따라 라이선스가 부여되었습니다.
wildermuth.com의 작업을 기반으로 합니다.
이 기사가 마음에 들면 Pluralsight에서 Shawn의 과정을 참조하십시오.
Reference
이 문제에 관하여(Angular에서 동적으로 구성 요소 생성), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/shawnwildermuth/dynamically-creating-components-in-angular-dag텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)