간단하지만 맞춤형 아코디언 부품

Angular에서 아주 간단한 아코디언 구성 요소를 만드는 방법Angular의 내용 투영 기능을 이용하여 다양한 방식으로 맞춤형 아코디언/확장 패널을 구축할 것입니다.

아코디언


아코디언은 보통 수직으로 쌓인 제목 목록으로 누르면 내용을 표시합니다.아코디언이나 확장성은 거의 모든 UI 라이브러리의 일부로 간주됩니다.
각 재료를 살펴보면 Expansion Panel(ref)이 있는데 Ng 가이드에서 간단한 Accordion(ref)이라고 불린다.

맞춤형 아코디언 만들기


우리가 세워야 할 것은 더욱 간단한 판본이다.여느 때와 마찬가지로, 그 배후의 모든 생각은 각도 변화의 가능성을 탐색하는 데 도움을 준다.이 블로그는 주로 Angular에서 Content Projection(ref)을 사용하여 다시 사용할 수 있고 맞춤형 UI 구성 요소를 만드는 방법에 관한 것이다.

우리는 어떠한 제3자 라이브러리에 의존하여 우리의 구성 요소를 구축하지 않을 것이다.우리는 이 글에서 Directives, TemplateRef, Animation 등을 사용할 것이다.

계획


만약 우리가 아코디언 부품의 해부 구조를 본다면, 우리는 안에 있는 모든 다른 항목을 수용할 수 있는 주요 부용기가 필요하다.항목마다 제목과 내용 부분을 포함합니다.

내용 부분은 완전히 동태적이니 우리는 걱정할 필요가 없다.머리글의 내용:
  • 머리글 및 전환 아이콘이 있는 기본 머리글
  • 사용자 지정 제목의 기본 제목
  • 완전 맞춤형 수확대
  • 건축 아코디언 부품


    우선 구성 요소를 위한 전용 모듈을 만듭니다.모듈과 함께 만들어야 할 항목은 다음과 같습니다.
  • 아코디언 모 부품
  • 아코디언 프로젝트 지령
  • 아코디언 헤드 명령
  • 아코디언 타이틀 명령
  • 아코디언 내용 지령
  • lib/
    ├─ accordion/
      ├─ directives/
        ├─ accordion-item.directive.ts
        ├─ accordion-content.directive.ts
        ├─ accordion-title.directive.ts
        ├─ accordion-header.directive.ts
      ├─ accordion.component.html
      ├─ accordion.component.css
      ├─ accordion.component.ts
      ├─ accordion.module.ts
    
    모듈의 모양은 다음과 같습니다.
    import { CommonModule } from "@angular/common";
    import { NgModule } from "@angular/core";
    
    import { AccordionComponent } from "./accordion.component";
    import { AccordionItem } from "./directives/accordion-item.directive";
    import { AccordionContent } from "./directives/accordion-content.directive";
    import { AccordionTitle } from "./directives/accordion-title.directive";
    import { AccordionHeader } from "./directives/accordion-header.directive";
    
    @NgModule({
      declarations: [
        AccordionComponent,
        AccordionItem,
        AccordionContent,
        AccordionTitle,
        AccordionHeader
      ],
      imports: [CommonModule],
      exports: [
        AccordionComponent,
        AccordionItem,
        AccordionContent,
        AccordionTitle,
        AccordionHeader
      ]
    })
    export class AccordionModule {}
    
    그들 중 대다수가 선택기로 사용되고 논리가 없기 때문에 우리는 우선 명령부터 시작한다.이 명령을 놓은 숙주 요소의 템플릿 인용에 접근할 수 있도록 TemplateRef을 주입합니다.

    내용 명령


    @Directive({
      selector: "[accordionContent]"
    })
    export class AccordionContent {
      constructor(public templateRef: TemplateRef<any>) {}
    }
    

    표제 명령


    @Directive({
      selector: "[accordionHeader]"
    })
    export class AccordionHeader {
      constructor(public templateRef: TemplateRef<any>) {}
    }
    

    표제 명령


    @Directive({
      selector: "[accordionTitle]"
    })
    export class AccordionTitle {
      constructor(public templateRef: TemplateRef<any>) {}
    }
    

    프로젝트 명령


    @Directive({
      selector: "accordion-item"
    })
    export class AccordionItem {
      @Input() title = "";
      @Input() disabled = false;
      @ContentChild(AccordionContent) content: AccordionContent;
      @ContentChild(AccordionTitle) customTitle: AccordionTitle;
      @ContentChild(AccordionHeader) customHeader: AccordionHeader;
    }
    
    141560, 우리는 사용자를 위해 104790의 데이터를 설정했다.우리는 @Input()(ref) 장식기를 사용하여 내용, 제목과 제목을 인용했다.
    다음은 템플릿에서 제목, 컨텐트 및 제목이 전달되는 방법입니다.
    <accordion-item>
         <ng-template accordionHeader>ng-template>
         <ng-template accordionTitle>ng-template>
         <ng-template accordionContent>ng-template>
    </accordion-item>
    
    기본 설정이 완료되면 주요 구성 요소는 @ContentChild() 또는 모 구성 요소입니다.

    아코디언 부품


    우리는 기본적으로 확장항을 관리하기 위해 하나의 상태만 관리할 수 있다.
    @Component({
      selector: "accordion",
      templateUrl: "./accordion.component.html",
      styleUrls: ["./accordion.component.css"],
      changeDetection: ChangeDetectionStrategy.OnPush,
    })
    export class AccordionComponent {
      expanded = new Set<number>();
      /**
       * Decides if the single item will be open at once or not.
       * In collapsing mode, toggling one would collapse others
       */
      @Input() collapsing = true;
    
      @ContentChildren(AccordionItem) items: QueryList<AccordionItem>;
    
      /**
       * Make the toggle function available to be called from
       * outside.
       * @param index - Index of the accordion item
       */
      getToggleState = (index: number) => {
        return this.toggleState.bind(this, index);
      };
    
      toggleState = (index: number) => {
        if (this.expanded.has(index)) {
          this.expanded.delete(index);
        } else {
          if (this.collapsing) {
            this.expanded.clear();
          }
          this.expanded.add(index);
        }
      };
    }
    
    Set은 현재 확장된 아코디언 프로젝트의 상태를 유지하는 데 사용됩니다.집합은 서로 다른 값을 보증한다.
      @ContentChildren(AccordionItem) items: QueryList<AccordionItem>;
    
    이것은 보기에서 내용을 교체하고 표시할 수 있는 템플릿의 아코디언 프로젝트를 제공합니다.AccordionComponent을 입력하여 아코디언 동작을 정의한 사용자입니다.그것은 아코디언이 펼쳐질 때 다른 항목을 닫을지 여부를 알려준다.
  • collasing=true는 한 번에 한 항목만 열 수 있도록
  • collasing=false는 여러 항목을 동시에 열 수 있음을 나타냅니다
  • collapsing이라는 함수를 추가하여 기본적으로 항목의 상태를 전환할 수 있습니다.이 항목의 인덱스를 전달합니다. 이 인덱스는 이 항목을 검사하고 펼치거나 접을 것입니다.toggleState 함수는 특수한 함수입니다. 잠시 후에 토론하겠습니다.

    아코디언 모듈 템플릿


    이제 이 모든 것이 어떻게 안배되었는지 봅시다.
    <section class="accordion">
      <div *ngFor="let item of items;index as i"
        class="accordion__item" [class.disabled]="item.disabled" [class.active]="expanded.has(i)">
        <ng-container
          [ngTemplateOutlet]="(item?.customHeader?.templateRef || defaultHeader)"
          [ngTemplateOutletContext]="{$implicit: item, index: i, toggle: getToggleState(i)}"></ng-container>
        <div class="accordion__content" [class.expanded]="expanded.has(i)" [@contentExpansion]="expanded.has(i) ? 'expanded':'collapsed'">
          <ng-container *ngTemplateOutlet="item?.content?.templateRef"></ng-container>
        </div>
      </div>
    </section>
    
    <ng-template #defaultHeader let-item let-index="index">
      <header class="accordion__header"
        (click)="item.disabled ? {} :toggleState(index)">
        <ng-container *ngTemplateOutlet="item?.customTitle?.templateRef || defaultTitle"></ng-container>
        <button class="accordion__toggle-btn" [disabled]="item.disabled">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 24 24" width="24" height="24">
            <path fill="none" d="M0 0h24v24H0z" />
            <path d="M12 13.172l4.95-4.95 1.414 1.414L12 16 5.636 9.636 7.05 8.222z"/>
          </svg>
        </button>
      </header>
      <ng-template #defaultTitle>
        <p class="accordion__title">{{item?.title}}</p>
      </ng-template>
    </ng-template>
    
    우리는 단지 getToggleState수조(Querylist)를 교체했을 뿐이다. 이것은 기본적으로 items 구성 요소에서 전달된 accordion-items의 목록이다.

    내용 투영


    <ng-container
          [ngTemplateOutlet]="(item?.customHeader?.templateRef || defaultHeader)"
          [ngTemplateOutletContext]="{$implicit: item, index: i, toggle: getToggleState(i)}">
    </ng-container>
    
    사용자가 사용자 정의 제목을 제공하면 이 템플릿이나 accordion을 사용합니다.우리는 defaultHeader(ref)이라는 물건을 사용하여 템플릿을 보기에 투영한다.ngTemplateOutlet은 일부 정보를 템플릿에 전달하는 데 사용됩니다.Dell은 다음과 같은 이점을 제공합니다.
  • ngTemplateOutletContext - 현재 아코디언 종목.
  • item - 아코디언 항목의 인덱스(전환 시 필요).
  • index - 아코디언 프로젝트를 전환할 수 있는 함수
  • toggle 속성은 현재 상하문과 그에 연결된 색인을 가진 함수입니다.따라서, 인덱스 값을 함수에 전달할 필요가 없이, 이 특정 항목은 언제 호출되든지 자동으로 전환됩니다.
    14174790(우리도 정확한 원인으로 함수 14156104790을 호출할 수 있다).
    getToggleState = (index: number) => {
      return this.toggleState.bind(this, index);
    };
    
    참고: 템플릿에서 메서드를 사용하는 것이 걱정되는 경우 코드를 보다 좋게 만드는 두 가지 방법이 있습니다.

    1. 기억 전환 방법


    import { memoize } from 'lodash-es';
    
    getToggleState = memoize((index: number) => {
      console.log('Called');
      return this.toggleState.bind(this, index);
    })
    

    2. 파이핑 사용자정의 사용


    @Pipe({
      name:'getToggleFunction'
    })
    export class TogglePipe implements PipeTransform{
      transform(i: number, toggleFn: Function){
        return () => toggleFn(i);
      }
    }
    
    템플릿을 원하는 대로 변경합니다.
    <ng-container 
      [ngTemplateOutlet]="(item?.customHeader?.templateRef || defaultHeader)"
      [ngTemplateOutletContext]="{$implicit: item, index: i, toggle: i | getToggleFunction: toggleState}">
    </ng-container>
    

    사용법


    다음은 arrow을 사용하는 방법입니다.
    <ng-template #defaultHeader let-item let-index="index"></ng-template>
    
    toggleState을 호출할 때, 이것은 우리가 추가한 은식 속성 (this) 을 가리킨다.이것은 사용자가 원하는 속성을 지정하지 않았을 때 getToggleState 값을 사용한다는 것을 의미할 뿐이다. (어떻게 ngTemplateOutletContext을 조회하는지 참조)let-item을 추가함으로써, 우리는 index 속성을 {$implicit: item}이라는 변수에 분배합니다.이렇게 하면 템플릿에서 변수를 사용할 수 있습니다.
    마지막으로, 이 구성 요소를 어떻게 사용하는지 봅시다.우선 default은 먼저 수입한 다음에 사용해야 한다.
    다음은 이 구성 요소를 사용하는 모든 다른 방법입니다.

    기본용법


    <accordion [collapsing]="collapsing">
        <accordion-item title="Super simple Accordion">
            <ng-template accordionContent>
              <div class="p-4">
                A simple and customizable accordion component.
              </div>
            </ng-template>
        </accordion-item>
    </accordion>
    

    사용자 정의 제목


    <accordion [collapsing]="collapsing">
       <accordion-item>
          <ng-template accordionTitle>
              <div class="flex space-x-2">
                <p>Custom Title</p>
              </div>
            </ng-template>
            <ng-template accordionContent>
                <div class="p-4">
                  This is a simple implementation where title part is custom.
                </div>
            </ng-template>
         </accordion-item>
    </accordion>
    

    사용자 정의 제목 포함


    <accordion [collapsing]="collapsing">
       <accordion-item title="Super simple Accordion">
         <ng-template accordionHeader let-toggle="toggle">
              <div class="flex items-center justify-between px-4 h-12 bg-purple-200">
                <p> Custom Header <span>(with custom toggle button)</span><p>
                <div class="flex space-x-2">
                  <button (click)="toggle()">Toggle</button>
                </div>
              </div>
            </ng-template>
            <ng-template accordionContent>
                <div class="p-4">
                  This is a <strong>complete custom header</strong> implementation.
                </div>
            </ng-template>
          </accordion-item>
    </accordion>
    
    먼저 index 함수를 정의한 다음 버튼 let-index="index"에서 이 함수를 사용하는 방법을 보십시오
    이것은angular에서 간단하지만 사용자 정의 아코디언 구성 요소를 만드는 방법입니다.

    보상:애니메이션


    사용자가 아코디언 항목을 전환할 때 내용 애니메이션을 설정하는 각도 애니메이션을 추가했습니다.
    이를 위해, 두 가지만 추가하면 된다.먼저 애니메이션을 index decorator(ref)에서 정의해야 합니다.
    @Component({
     // --- removed for brevity
      animations: [
        trigger('contentExpansion', [
          state('expanded', style({height: '*', opacity: 1, visibility: 'visible'})),
          state('collapsed', style({height: '0px', opacity: 0, visibility: 'hidden'})),
          transition('expanded <=> collapsed',
            animate('200ms cubic-bezier(.37,1.04,.68,.98)')),
        ])
      ]
    })
    export class AccordionComponent {}
    
    그런 다음 템플릿에서 다음을 수행합니다.
    <div class="accordion__content" [@contentExpansion]="expanded.has(i) ? 'expanded':'collapsed'">
          <ng-container *ngTemplateOutlet="item?.content?.templateRef"></ng-container>
    </div>
    
    애니메이션 트리거를 AccordionModule에 추가하고 확장 조건에 따라 상태를 전달합니다.이것은 판넬을 전환할 때 우리에게 매끄러운 애니메이션을 제공했다.
    아코디언에 필요한 모든 스타일은 toggle 파일에 있습니다.TailwindCSS는 기본 응용 프로그램의 스타일만 설정하는 데 사용됩니다.

    코드 및 데모


    데모: https://ssscp.csb.app
    코드: https://codesandbox.io/s/ng-accordion-ssscp
    파이핑 코드: https://codesandbox.io/s/ng-accordion-optimized-49bxr

    연락 주세요.


  • Github
  • 반드시 평론 부분에 너의 생각을 첨가해야 한다.
    보안 유지❤️

    좋은 웹페이지 즐겨찾기