programing

Angular에서 동적으로 구성요소 추가 및 제거

goodsources 2023. 8. 29. 20:29
반응형

Angular에서 동적으로 구성요소 추가 및 제거

현재의 공식 문서는 다음과 같이 구성 요소동적으로 변경하는 방법만 보여줍니다.<ng-template>태그. https://angular.io/guide/dynamic-component-loader

제가 달성하고자 하는 것은 다음과 같은 세 가지 구성요소가 있다고 가정해 보겠습니다.header,section,그리고.footer다음 선택기를 사용합니다.

<app-header>
<app-section>
<app-footer>

그런 다음 각 구성 요소를 추가하거나 제거하는 6개의 버튼이 있습니다.Add Header,Add Section,그리고.Add Footer

그리고 내가 클릭할 때Add Header페이지가 추가됩니다.<app-header>페이지에 다음 내용을 포함하도록 렌더링하는 페이지로 이동합니다.

<app-header>

그리고 나서 내가 클릭하면Add Section이제 페이지에 다음 항목이 포함됩니다.

<app-header>
<app-section>
<app-section>

그리고 내가 클릭하면Add Footer이제 페이지에 다음 구성 요소가 모두 포함됩니다.

<app-header>
<app-section>
<app-section>
<app-footer>

Angular에서 이것을 달성하는 것이 가능합니까?참고:ngFor페이지에 다른 구성 요소가 아닌 동일한 구성 요소만 추가할 수 있기 때문에 제가 찾고 있는 솔루션이 아닙니다.

편집:ngIf그리고.ngFor템플릿이 이미 정해져 있기 때문에 제가 찾고 있는 해결책은 아닙니다.제가 찾고 있는 것은 한 무더기의component애잔arraycomponents의 인덱스를 추가, 제거 및 변경할 수 있습니다.array쉽게.

EDIT 2: 좀 더 명확하게 하기 위해, 그 이유에 대한 또 다른 예를 들어 보겠습니다.ngFor작동하지 않습니다.다음과 같은 구성 요소가 있다고 가정합니다.

<app-header>
<app-introduction>
<app-camera>
<app-editor>
<app-footer>

이제 새로운 구성 요소가 등장합니다.<app-description>사용자가 와 사이에 삽입하려는 항목<app-editor>.ngFor반복하고 싶은 동일한 구성 요소가 있는 경우에만 작동합니다.하지만 다른 구성 요소에 대해서는,ngFor여기서 실패합니다.

다음을 사용하여 동적으로 구성 요소를 생성하여 달성하려는 작업을 수행할 수 있습니다.ComponentFactoryResolver그리고 나서 그것들을 주입합니다.ViewContainerRef동적으로 이를 수행하는 한 가지 방법은 구성 요소의 클래스를 구성 요소를 만들고 주입할 함수의 인수로 전달하는 것입니다.

아래 예를 참조하십시오.

import {
  Component,
  ComponentFactoryResolver, Type,
  ViewChild,
  ViewContainerRef
} from '@angular/core';

// Example component (can be any component e.g. app-header app-section)
import { DraggableComponent } from './components/draggable/draggable.component';

@Component({
  selector: 'app-root',
  template: `
    <!-- Pass the component class as an argument to add and remove based on the component class -->
    <button (click)="addComponent(draggableComponentClass)">Add</button>
    <button (click)="removeComponent(draggableComponentClass)">Remove</button>

    <div>
      <!-- Use ng-template to ensure that the generated components end up in the right place -->
      <ng-template #container>

      </ng-template>
    </div>

  `
})
export class AppComponent {
  @ViewChild('container', {read: ViewContainerRef}) container: ViewContainerRef;

  // Keep track of list of generated components for removal purposes
  components = [];

  // Expose class so that it can be used in the template
  draggableComponentClass = DraggableComponent;

  constructor(private componentFactoryResolver: ComponentFactoryResolver) {
  }

  addComponent(componentClass: Type<any>) {
    // Create component dynamically inside the ng-template
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentClass);
    const component = this.container.createComponent(componentFactory);

    // Push the component so that we can keep track of which components are created
    this.components.push(component);
  }

  removeComponent(componentClass: Type<any>) {
    // Find the component
    const component = this.components.find((component) => component.instance instanceof componentClass);
    const componentIndex = this.components.indexOf(component);

    if (componentIndex !== -1) {
      // Remove component from both view and array
      this.container.remove(this.container.indexOf(component));
      this.components.splice(componentIndex, 1);
    }
  }
}

주의:

  1. 나중에 구성 요소를 쉽게 제거하려면 로컬 변수에서 해당 구성 요소를 추적할 수 있습니다.this.components또는 내부의 모든 요소를 루프할 수 있습니다.ViewContainerRef.

  2. 구성요소를 항목 구성요소로 등록해야 합니다.모듈 정의에서 구성 요소를 항목 구성 요소(entryComponents: [DraggableComponent]).

실행 예: https://plnkr.co/edit/mrXtE1ICw5yeIUke7wl5

자세한 내용은 https://angular.io/guide/dynamic-component-loader 에서 확인하시기 바랍니다.

Angular v13 이상 - DOM에 동적 구성 요소를 쉽게 추가할 수 있는 방법

parent.component.html

<ng-template #viewContainerRef></ng-template>

parent.component.ts

@ViewChild("viewContainerRef", { read: ViewContainerRef }) vcr!: ViewContainerRef;
ref!: ComponentRef<YourChildComponent>

addChild() {
  this.ref = this.vcr.createComponent(YourChildComponent)
}

removeChild() {
  const index = this.vcr.indexOf(this.ref.hostView)
  if (index != -1) this.vcr.remove(index)
}

각도 v12 이하

동적 추가 및 제거 프로세스를 보여주는 데모를 만들었습니다.상위 구성 요소는 하위 구성 요소를 동적으로 생성하고 제거합니다.

데모를 보려면 클릭

상위 구성 요소

// .ts
export class ParentComponent {
  @ViewChild("viewContainerRef", { read: ViewContainerRef })
  VCR: ViewContainerRef;

  child_unique_key: number = 0;
  componentsReferences = Array<ComponentRef<ChildComponent>>()

  constructor(private CFR: ComponentFactoryResolver) {}

  createComponent() {
    let componentFactory = this.CFR.resolveComponentFactory(ChildComponent);

    let childComponentRef = this.VCR.createComponent(componentFactory);

    let childComponent = childComponentRef.instance;
    childComponent.unique_key = ++this.child_unique_key;
    childComponent.parentRef = this;

    // add reference for newly created component
    this.componentsReferences.push(childComponentRef);
  }

  remove(key: number) {
    if (this.VCR.length < 1) return;

    let componentRef = this.componentsReferences.filter(
      x => x.instance.unique_key == key
    )[0];

    let vcrIndex: number = this.VCR.indexOf(componentRef as any);

    // removing component from container
    this.VCR.remove(vcrIndex);

    // removing component from the list
    this.componentsReferences = this.componentsReferences.filter(
      x => x.instance.unique_key !== key
    );
  }
}

// .html
<button type="button" (click)="createComponent()">
    I am Parent, Create Child
</button>
<div>
    <ng-template #viewContainerRef></ng-template>
</div>

하위 구성 요소

// .ts
export class ChildComponent {

  public unique_key: number;
  public parentRef: ParentComponent;

  constructor() {
  }

  remove_me() {
    console.log(this.unique_key)
    this.parentRef.remove(this.unique_key)
  }
}

// .html
<button (click)="remove_me()">I am a Child {{unique_key}}, click to Remove</button>

언급URL : https://stackoverflow.com/questions/44939878/dynamically-adding-and-removing-components-in-angular

반응형