Angular Material Mat에 액세스 옵션 패널 컨테이너 선택

9394 단어 angular
이 기사에서는 이상한 전역 DOM 쿼리를 수행하지 않고 프로그래밍 방식으로 Angular Material Select 패널에 액세스하는 방법을 살펴보겠습니다 😃. 다이빙하자!


TL;DR



디렉티브에서 MatSelect 에 대한 참조를 삽입하고 openedChange Observable을 구독하고 열려 있는 경우 panelMatSelect 속성에 액세스합니다.




고품질 구성 요소 라이브러리를 찾고 있다면 Angular Material이 좋은 시작점이 될 수 있습니다. 참고로 머티리얼 디자인을 검색하지 않는 경우 다른 흥미로운 옵션이 많이 있습니다.

  • the CDK package 디자인에 구애받지 않는 Angular Material 패키지 내

  • Bootstrap 기반
  • ng-bootstrap
  • ngx-bootstrap

  • VMWare Clarity Design System
  • Nebular
  • Prime Faces
  • (...그리고 a lot more ...)

  • 그러나 우리 주제로 돌아갑니다. Angular Material은 액세스 가능한 구성 요소를 만드는 데 많은 노력을 기울입니다. 경우에 따라 사용자 지정 특성과 같은 일부 사용자 지정 논리를 추가해야 할 수 있습니다. 예를 들어 MatSelect ( here are the corresponding docs )




    이에 대한 Angular 템플릿은 다음과 같습니다.

    <mat-select [(ngModel)]="selectedValue" name="food">
      <mat-option *ngFor="let food of foods" [value]="food.value">
        {{food.viewValue}}
      </mat-option>
    </mat-select>
    


    내 클라이언트는 렌더링된 옵션에 액세스하고 스크린 리더에 대한 지원을 강화하기 위해 해당 옵션에 사용자 정의 속성을 추가해야 한다는 요구 사항이 있었습니다<options>. 따라서 첫 번째 아이디어는 myDirective(적절한 이름을 사용하세요 😉)와 ​​같은 지시문을 <mat-select>에 배치한 다음 일부 DOM 선택기를 사용하여 옵션을 확보하는 것입니다.

    재료 옵션 패널은 MatSelect의 하위 항목이 아닙니다.



    쉬워보이겠죠? 지시문myDirective에서 ElementRef를 주입하고 간단히 <mat-options>에 액세스할 수 있습니다. ElementRef는 하위 옵션 항목을 선택할 수 있는 <mat-select> 중 하나입니다. 같은 것

    @Directive({})
    export class MyDirective implements OnInit {
    
       constructor(private elementRef: ElementRef) {}
    
       ngOnInit() {
          this.elementRef.nativeElement.querySelector(...)
       }
    }
    


    작동하지 않습니다! <mat-options><mat-select>를 작성하는 방법에서 보일 수 있지만 DOM에서 <mat-select>의 자식 객체가 아닙니다.

    선택 항목을 열면 Material은 document.body 수준의 전용 Z-인덱스 및 절대 위치 패널에서 해당 항목을 렌더링합니다. 왜 그런 겁니까? 그것은 다른 모든 요소 위에 머무르고 본문 내의 다른 요소를 확장하거나 이동하지 않도록 하기 위한 것입니다.



    당신은 잘못하고있어



    다음 즉각적인 단계는 this.elementRef.nativeElement.querySelector(...)document.body.querySelector(...)로 변경하는 것입니다. 맞습니까? 하지 마라! 우리는 그것을 최후의 수단으로만 유지합니다. 성능상의 이유로 querySelector에 최대한 집중하고 페이지에 렌더링된 다른 요소에 부딪히지 않도록 해야 합니다.

    패널 속성을 통해 옵션 패널 참조



    오픈 소스 라이브러리 사용의 가장 큰 장점은 소스를 살펴보고 Material이 호스팅 오버레이를 생성하는 방법과 참조를 유지하고 특히 외부에 노출하는지 여부를 확인할 수 있다는 것입니다. 그리고 실제로 우리가 have a quick look at the API docs 이면 panel 의 컨테이너에 대한 ElementRef 인 속성 <options> 가 있습니다.



    해당 패널 속성에서 panel.nativeElement.querySelect(...)를 수행하여 옵션 목록이 있는 컨테이너에서만 실행되는 적절한 범위의 DOM 쿼리를 가질 수 있습니다.

    종속성 주입으로 호스트 구성 요소에 액세스



    다음과 같이 <mat-select>에 지시문을 추가합니다.

    <mat-select myDirective>
      ...
    </mat-select>
    


    지시문 s.t. 내에서 MatSelect 인스턴스에 액세스할 수 있는 방법만 있으면 됩니다. panel 참조를 잡고 쿼리를 수행할 수 있습니다. 가장 쉬운 방법(놀랍게도 많은 개발자가 이에 대해 알지 못함)은 Angular의 종속성 주입을 사용하는 것입니다. 생성자에 인스턴스를 요구함으로써 Angular는 호스트/부모 구성 요소를 주입하도록 주의를 기울일 것입니다.

    @Directive({
      selector: '[myDirective]'
    })
    export class MyDirective implements OnInit {
    
      /**
       *  MatSelect instance injected into the directive
       */
      constructor(private select:MatSelect) { }
    
    }
    


    이제 남은 것은 실제로 panel 속성을 사용하는 것입니다. 옵션은 openedChange가 활성화된 경우에만 페이지에서 렌더링되고 표시되므로 <mat-select> Observable을 구독해야 합니다.

    @Directive({
      selector: '[myDirective]'
    })
    export class MyDirective implements OnInit {
    
      constructor(private select:MatSelect) { }
    
      ngOnInit() {
        this.select.openedChange.subscribe(isOpen => {
          if(isOpen) {
            console.log('open', this.select.panel);
          }
        })
      }
    }
    


    전체 예



    다음은 놀 수 있는 Stackblitz 예제입니다.

    https://stackblitz.com/edit/blog-angular-mat-select-panel-options

    좋은 웹페이지 즐겨찾기