가상 드롭다운
Ignite UI for Angular Drop Down 구성 요소는 선택할 항목의 매우 큰 목록을 표시하기 위해 지시문과 IgxForOf
완전히 통합 될 수 있습니다.
Angular 가상 드롭 다운 예제
이 샘플이 마음에 드시나요? 전체 Ignite UI for Angular 툴킷에 액세스하고 몇 분 안에 나만의 앱을 구축해 보세요. 무료로 다운로드하세요.
용법
첫 번째 단계
가상 아이템 목록을 표시하도록 드롭다운을 구성하려면 몇 가지 전제 조건을 충족해야 합니다. 먼저 드롭다운을 선언할 구성 요소의 모듈에서 IgxForOfModule
가져와야 합니다.
// app.module.ts
import { IgxForOfModule } from 'igniteui-angular';
// import { IgxForOfModule } from '@infragistics/igniteui-angular'; for licensed package
@NgModule({
imports: [
...
IgxForOfModule
]
})
export class AppModule {}
typescript
템플릿 구성
다음으로 드롭다운 구성요소의 템플릿을 생성하고 다음을 사용하여 데이터를 반복해야 합니다. *igxFor
대신에 *ngFor
. 그만큼 *igxFor
모든 항목을 올바르게 표시하려면 지시문에 몇 가지 추가 구성이 필요합니다.
<!-- drop-down-virtual.component.html -->
<button igxButton [igxToggleAction]="dropdown"
[igxDropDownItemNavigation]="dropdown">
Item Series
</button>
<igx-drop-down #dropdown>
<div class="drop-down-virtual-wrapper" style="height: {{ itemsMaxHeight }}px;">
<igx-drop-down-item
*igxFor="let item of items; index as index;
scrollOrientation: 'vertical';
containerSize: itemsMaxHeight;
itemSize: itemHeight;"
[value]="item" [isHeader]="item.header"
role="option" [disabled]="item.disabled"
[index]="index">
{{ item.name }}
</igx-drop-down-item>
</div>
</igx-drop-down>
<div>Selected Model: <span>{{ dropdown.selectedItem?.value.name }}</span></div>
html
*igxFor
지시문에 전달되는 추가 매개변수는 다음과 같습니다.
index
- 데이터 세트에서 현재 항목의 인덱스를 캡처합니다.scrollOrientation
- 항상'vertical'
여야 합니다.containerSize
- 가상화된 컨테이너의 크기(px
단위)입니다. 이는<div>
래핑에도 적용되어야 합니다.itemSize
- 표시될 항목의 크기(px
단위)
항목의 고유성을 보장하려면 다음을 통과하십시오. item
내부 value
입력 및 index
내부 index
의 입력 igx-drop-down-item
. 스크롤하는 동안 선택을 유지하려면 드롭다운 항목에 바인딩된 데이터 항목에 대한 참조가 있어야 합니다.
각 항목에 대해 [value]
입력에 고유한 값을 전달하는 것이 좋습니다. 그렇지 않으면 예상치 못한 결과(잘못된 선택)가 발생할 수 있습니다.
드롭다운에서 가상화된 항목을 사용하는 경우 dropdown.selectedItem
의 유형은 { value: any, index: number }
가 됩니다. 여기서 value
[value]
입력 내부에 전달된 데이터 항목에 대한 참조이고 index
는 항목의 인덱스입니다. 데이터 세트
구성 요소 정의
구성 요소 생성자 내에서 드롭다운에 표시될 적당히 큰 항목 목록(헤더와 비활성화된 항목을 모두 포함)을 선언합니다. itemHeight
및 itemsMaxHeight
도 선언해야 합니다.
// drop-drop-virtual.component.ts
export class DropDownVirtualComponent {
public items: DataItem[];
public itemHeight = 48;
public itemsMaxHeight = 320;
constructor() {
const itemsCollection: DataItem[] = [];
for (let i = 0; i < 50; i++) {
const series = (i * 10).toString();
itemsCollection.push({
id: series,
name: `${series} Series`,
header: true,
disabled: false
});
for (let j = 0; j < 10; j++) {
itemsCollection.push({
id: `${series}_${j}`,
name: `Series ${series}, ${i * 10 + j} Model`,
header: false,
disabled: j % 9 === 0
});
}
}
this.items = itemsCollection;
}
}
typescript
스타일
구성의 마지막 부분은 두 개의 스크롤 막대(igxFor
에서 하나, 컨테이너 자체에서 하나)가 나타나는 것을 방지하기 위해 래핑 div에 overflow: hidden
설정하는 것입니다.
// drop-drop-virtual.component.scss
.drop-down-virtual-wrapper {
overflow: hidden;
}
scss
원격 데이터
igx-drop-down
*igxFor
구조 지시문을 사용하여 원격 데이터 청크 로드를 지원합니다. 구성은 로컬 항목의 구성과 유사하며, 주요 차이점은 데이터 청크가 로드되는 방식입니다.
주형
드롭다운 템플릿은 이전 예제와 비교했을 때 크게 변경할 필요가 없습니다. 여전히 래핑 div를 지정하고, 그에 따라 스타일을 지정하고, *igxFor
에 대한 전체 구성을 작성해야 합니다. 원격 소스에서 데이터를 가져오므로 데이터가 관찰 가능하도록 지정하고 Angular의 async
파이프를 통해 전달해야 합니다.
<igx-drop-down #remoteDropDown>
<div class="drop-down-virtual-wrapper">
<igx-drop-down-item
*igxFor="let item of rData | async; index as index;
scrollOrientation: 'vertical';
containerSize: itemsMaxHeight;
itemSize: itemHeight;"
[value]="item.ProductName" role="option"
[disabled]="item.disabled" [index]="index">
{{ item.ProductName }}
</igx-drop-down-item>
</div>
</igx-drop-down>
html
청크 로드 처리
보시다시피 템플릿은 이전 예의 템플릿과 거의 동일합니다. 이 원격 데이터 시나리오에서는 뒤에 숨은 코드가 대부분의 무거운 작업을 수행합니다.
먼저 데이터를 가져오기 위한 원격 서비스를 정의해야 합니다.
// remote.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { IForOfState } from 'igniteui-angular';
// import { IForOfState } from '@infragistics/igniteui-angular'; for licensed package
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable()
export class RemoteService {
public remoteData: Observable<any[]>;
private _remoteData: BehaviorSubject<any[]>;
constructor(private http: HttpClient) {
this._remoteData = new BehaviorSubject([]);
this.remoteData = this._remoteData.asObservable();
}
public getData(data?: IForOfState, cb?: (any) => void): any {
// Assuming that the API service is RESTful and can take the following:
// skip: start index of the data that we fecth
// count: number of records we fetch
this.http.get(`https://dummy.db/dummyEndpoint?skip=${data.startIndex}&count=${data.chunkSize}`).subscribe((data) => {
// emit the values through the _remoteData subject
this._remoteData.next(data);
})
}
typescript
이 서비스는 remoteData
아래에 Observable
노출합니다. 서비스를 주입하고 원격 드롭다운 구성 요소에 해당 속성을 바인딩합니다.
// remote-drop-down.component.ts
@Component({
providers: [RemoteService],
selector: 'app-drop-down-remote',
templateUrl: './drop-down-remote.component.html',
styleUrls: ['./drop-down-remote.component.scss']
})
export class DropDownRemoteComponent implements OnInit, OnDestroy {
@ViewChild(IgxForOfDirective, { read: IgxForOfDirective })
public remoteForDir: IgxForOfDirective<any>;
@ViewChild('remoteDropDown', { read: IgxDropDownComponent })
public remoteDropDown: IgxDropDownComponent;
public itemHeight = 48;
public itemsMaxHeight = 480;
public prevRequest: Subscription;
public rData: any;
private destroy$ = new Subject();
constructor(private remoteService: RemoteService) { }
public ngAfterViewInit() {
const initialState = { startIndex: 0, chunkSize: Math.ceil(this.itemsMaxHeight / this.itemHeight) }
this.remoteService.getData(initialState, (data) => {
this.remoteForDir.totalItemCount = data['@odata.count'];
});
// Subscribe to igxForOf.chunkPreload and load new data from service
this.remoteForDir.chunkPreload.pipe(takeUntil(this.destroy$)).subscribe((data) => {
this.dataLoading(data);
});
}
public dataLoading(evt) {
if (this.prevRequest) {
this.prevRequest.unsubscribe();
}
this.prevRequest = this.remoteService.getData(
evt,
(data) => {
this.remoteForDir.totalItemCount = data['@odata.count'];
});
}
public ngOnInit() {
this.rData = this.remoteService.remoteData;
}
public ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}
typescript
ngAfterViewInit
후크 내에서 초기 상태에 대한 데이터를 가져오고 igxForOf
지시문의 chunkPreload
이미터를 구독하기 위해 호출합니다. 이 구독은 로드된 청크가 변경될 때마다 데이터를 가져오는 역할을 담당합니다. 우리는 pipe(takeUntil(this.destroy$))
사용하므로 구성 요소 삭제 시 이미터에서 쉽게 구독을 취소할 수 있습니다.
원격 가상화 - 데모
위 구성의 결과는 스크롤 막대의 상태에 따라 표시해야 하는 데이터를 동적으로 로드하는 드롭다운입니다.
참고 및 제한 사항
가상화된 항목 목록과 함께 드롭다운을 사용하면 몇 가지 제한 사항이 적용됩니다. *igxFor
사용하여 드롭다운 목록을 설정하려고 할 때 다음 사항에 유의하십시오.
- 반복되는 드롭다운 항목은 다음 CSS가 포함된 래핑 요소(예:
<div>
)로 전달되어야 합니다.overflow: hidden
및height
px
단위의containerSize
크기와 같습니다. <igx-drop-down-item-group>
목록이 가상화된 경우 항목을 그룹화하는 데 사용할 수 없습니다.isHeader
대신 속성을 사용하십시오.-
items
접근자는 현재 가상화된 보기에 있는 헤더가 아닌 드롭다운 항목의 목록만 반환합니다. dropdown.selectedItem
은{ value: any, index: number }
유형입니다.-
selection
항목에 의해 방출된 객체const emittedEvent: { newSelection: { value: any, index: number }, oldSelection: { value: any, index: number }, cancel: boolean, }
dropdown.setSelectedItem
데이터 세트의 항목 색인으로 호출되어야 합니다.- 드롭다운 항목의
[selected]
입력을 설정하면 드롭다운 선택 항목에 항목이 표시되지 않습니다.