가상 드롭다운
Ignite UI for Angular 선택 항목의 매우 큰 목록을 표시하기 위해 IgxForOf 지시문과 완전히 통합될 수 있습니다.
Angular Virtual Drop Down Example
Usage
First Steps
가상 아이템 목록을 표시하도록 드롭다운을 구성하려면 몇 가지 전제 조건을 충족해야 합니다. 먼저 드롭다운을 선언할 구성 요소의 모듈에서 IgxForOfModule
가져와야 합니다.
// app.module.ts
import { IgxForOfModule } from 'igniteui-angular';
// import { IgxForOfModule } from '@infragistics/igniteui-angular'; for licensed package
@NgModule({
imports: [
...
IgxForOfModule
]
})
export class AppModule {}
Template Configuration
다음으로 드롭다운 구성요소의 템플릿을 생성하고 다음을 사용하여 데이터를 반복해야 합니다. *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>
*igxFor
지시문에 전달되는 추가 매개변수는 다음과 같습니다.
index
- 데이터 세트에서 현재 항목의 인덱스를 캡처합니다.scrollOrientation
- 항상'vertical'
여야 합니다.containerSize
- 가상화된 컨테이너의 크기(px
단위)입니다. 이는<div>
래핑에도 적용되어야 합니다.itemSize
- 표시될 항목의 크기(px
단위)
항목의 고유성을 보장하려면 다음을 통과하십시오. item
내부 value
입력 및 index
내부 index
의 입력 igx-drop-down-item
. 스크롤하는 동안 선택을 유지하려면 드롭다운 항목에 바인딩된 데이터 항목에 대한 참조가 있어야 합니다.
Note
각 항목에 대해 [value]
입력에 고유한 값을 전달하는 것이 좋습니다. 그렇지 않으면 예상치 못한 결과(잘못된 선택)가 발생할 수 있습니다.
Note
드롭다운에서 가상화된 항목을 사용하는 경우 dropdown.selectedItem
의 유형은 { value: any, index: number }
가 됩니다. 여기서 value
[value]
입력 내부에 전달된 데이터 항목에 대한 참조이고 index
는 항목의 인덱스입니다. 데이터 세트
Component Definition
구성 요소 생성자 내에서 드롭다운에 표시될 적당히 큰 항목 목록(헤더와 비활성화된 항목을 모두 포함)을 선언합니다. 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;
}
}
Styles
구성의 마지막 부분은 두 개의 스크롤 막대(igxFor
에서 하나, 컨테이너 자체에서 하나)가 나타나는 것을 방지하기 위해 래핑 div에 overflow: hidden
설정하는 것입니다.
// drop-drop-virtual.component.scss
.drop-down-virtual-wrapper {
overflow: hidden;
}
Remote Data
igx-drop-down
*igxFor
구조 지시문을 사용하여 원격 데이터 청크 로드를 지원합니다. 구성은 로컬 항목의 구성과 유사하며, 주요 차이점은 데이터 청크가 로드되는 방식입니다.
Template
드롭다운 템플릿은 이전 예와 비교하여 많이 변경할 필요가 없습니다. 여전히 래핑 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>
Handling chunk load
보시다시피 템플릿은 이전 예의 템플릿과 거의 동일합니다. 이 원격 데이터 시나리오에서는 뒤에 숨은 코드가 대부분의 무거운 작업을 수행합니다.
먼저 데이터를 가져오기 위한 원격 서비스를 정의해야 합니다.
// 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);
})
}
이 서비스는 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();
}
}
ngAfterViewInit
후크 내에서 초기 상태에 대한 데이터를 가져오고 igxForOf
지시문의 chunkPreload
이미터를 구독하기 위해 호출합니다. 이 구독은 로드된 청크가 변경될 때마다 데이터를 가져오는 역할을 담당합니다. 우리는 pipe(takeUntil(this.destroy$))
사용하므로 구성 요소 삭제 시 이미터에서 쉽게 구독을 취소할 수 있습니다.
Remote Virtualization - Demo
위 구성의 결과는 스크롤 막대의 상태에 따라 표시해야 하는 데이터를 동적으로 로드하는 드롭다운입니다.
Notes and Limitations
가상화된 항목 목록과 함께 드롭다운을 사용하면 몇 가지 제한 사항이 적용됩니다. *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]
입력을 설정하면 드롭다운 선택 항목에 항목이 표시되지 않습니다.