깜놀하는 해므찌로

Angular ScrollService 구현 예시 / scroll 본문

IT

Angular ScrollService 구현 예시 / scroll

agnusdei1207 2023. 9. 1. 23:23
반응형
SMALL
import { ElementRef, Injectable, QueryList } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class ScrollService {
  subject$ = new Subject(); // 스크롤 이벤트를 전달하기 위한 Subject 객체

  select(index: number) {
    this.subject$.next(index); // 주어진 인덱스를 Subject에 전달하여 구독자들에게 알림
  }

  scrollTo(found: ElementRef<HTMLElement>) {
    if (found) {
      const layout = document.querySelector('#layout'); // id가 'layout'인 요소를 가져옴

      // 스크롤 위치 계산
      const top =
        found.nativeElement.getBoundingClientRect().top +
        layout.scrollTop -
        layout.clientTop -
        70;

      if (layout) {
        layout.scrollTo({
          top: top,
          behavior: 'smooth', // 부드러운 스크롤 동작 설정
        });
      }
    }
  }

  observe(sections: QueryList<ElementRef<HTMLElement>>) {
    this.subject$.subscribe((index: number) => {
      const found = sections.find((section, i) => i === index); // 주어진 인덱스에 해당하는 요소를 찾음
      this.scrollTo(found); // 해당 요소로 스크롤 이동
    });
  }
}

1. 스크롤 서비스

 

 

<section #sections></section>
<section #sections></section>
<section #sections></section>
<section #sections></section>
<section #sections></section>

 

2. 템플릿 예시 

 @ViewChildren('sections') sections!: QueryList<ElementRef<HTMLElement>>;
 
 
 ngAfterViewInit(): void { // 템플릿이 전부 그려진 후
    this.scrollService.observe(this.sections); // 섹션들 HTML 객체 타입으로 전달
  }

3.. 컴포넌트 내부

`QueryList`는 Angular에서 제공하는 컬렉션 타입으로, 여러 개의 DOM 요소에 대한 참조를 저장하고 관리하는 기능을 제공합니다. `QueryList`는 주로 `@ViewChildren` 데코레이터와 함께 사용되어 템플릿에서 선택자를 사용하여 여러 DOM 요소를 참조하는 데 유용합니다. 

1. 요소 추가 및 제거: `QueryList`는 동적으로 요소를 추가하거나 제거할 수 있는 기능을 제공합니다. 즉, DOM에 새로운 요소가 추가되거나 삭제되면 `QueryList`도 자동으로 업데이트됩니다.

2. 요소 순회: `QueryList`는 `forEach()` 메서드를 통해 내부에 저장된 요소들을 순회할 수 있습니다. 이를 통해 각 요소에 접근하고 작업을 수행할 수 있습니다.

3. 변경 감지: `QueryList`는 내부 요소의 상태 변경을 감지할 수 있습니다. 예를 들어, 요소의 속성이 변경되면 `QueryList`는 이를 감지하여 자동으로 업데이트됩니다.

4. 이벤트 감지: `QueryList`는 내부 요소에서 발생하는 이벤트를 감지할 수 있습니다. 이를 통해 특정 이벤트에 대한 처리를 수행하거나 상호작용할 수 있습니다.

따라서, 주어진 코드에서 `sections` 변수는 `QueryList<ElementRef<HTMLElement>>` 타입으로 선언되어 여러 DOM 요소의 참조를 저장하고 관리합니다. 이를 통해 템플릿에서 선택자를 사용하여 해당 요소들에 접근하고 조작할 수 있습니다. 변경된 요소에 대한 업데이트 및 이벤트 감지도 자동으로 처리됩니다.

 

 

<div
        class="flex flex-col justify-start gap-2.5 cursor-pointer p-2 bg-gray-50"
        *ngFor="let child of menu.children; index as i"
      >
        <div (click)="_scrollTo(i)">
          <div
            class="font-semibold text-sm text-gray-800 hover:bg-gray-100 py-2 rounded-xl px-10 w-full"
          >
            <p>{{ child.name }}</p>
          </div>
        </div>
      </div>

4. 컴포넌트의 컴포넌트 (click) 이벤트에 달아서 활용

 

 
 _scrollTo(index: number) {
    this.scrollService.select(index);
  }

5. select 를 활용하여 propagate !

반응형
LIST