콤보박스 원격 바인딩

    Ignite UI for Angular 콤보 상자를 원격 서비스에 바인딩하고 필요에 따라 데이터를 검색할 수 있는 API를 제공합니다.

    Angular ComboBox Remote Binding Example

    아래 샘플은 dataPreLoad 속성을 사용하여 원격 데이터의 새 청크를 로드하는 원격 바인딩을 보여줍니다.

    Usage

    ComboBox 컴포넌트를 시작하려면 먼저 다음 부품을 가져와야 합니다IgxComboModule 당신의 app.module.ts 파일. 이 데모에서는 서버 요청을 위해 원격 서비스를 사용하므로 다음을 포함해야 합니다HttpClientModule:

    import { IgxComboModule } from 'igniteui-angular/combo';
    // import { IgxComboModule } from '@infragistics/igniteui-angular'; for licensed package
    
    import { HttpClientModule } from '@angular/common/http';
    
    @NgModule({
        imports: [
            ...
            IgxComboModule,
            HttpClientModule,
            ...
        ]
    })
    export class AppModule {}
    

    Define Remote Service

    콤보박스를 원격 데이터에 바인딩할 때 서버에서 요청 시 데이터를 로드할 수 있는 서비스가 필요합니다. 콤보박스 구성 요소는 콤보박스의 현재 상태(첫 번째 인덱스 및 로드해야 하는 항목 수)를 제공하는 virtualizationState 속성을 노출합니다. 스크롤 크기를 제대로 표시하려면 totalItemCount 속성에 서버의 전체 항목에 해당하는 값이 있어야 합니다.

    아래 코드는 콤보박스의 현재 상태 정보를 받고 데이터를 관찰 가능한 것으로 반환하는 메서드를 가진getData() 간단한 서비스를 정의합니다:

    import { HttpClient } from '@angular/common/http';
    import { Injectable } from '@angular/core';
    import { IForOfState } from 'igniteui-angular/directives';
    // 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();
        }
    
        // Use combobox current virtualization state and search text to build URL and request the new data.
        public getData(data?: IForOfState, searchText?: string, cb?: (any) => void): any { }
    }
    

    Binding ComboBox to Remote Service

    서비스에서 데이터가 관찰 가능 항목으로 반환되면 비동기 파이프를 사용하여 이를 콤보박스 구성 요소로 설정할 수 있습니다.

    <igx-combo [data]="rData | async"
               [valueKey]="'ProductID'"
               [displayKey]="'ProductName'"
               (dataPreLoad)="dataLoading($event)"
               (searchInputUpdate)="handleSearchInputUpdate($event)"
               (selectionChanging)="handleSelectionChanging($event)"
               (closing)="onClosing()"
               (opened)="onOpened()"
               (closed)="onClosed()"
               [disableFiltering]="false">
    </igx-combo>
    

    다음은 콤보박스 컴포넌트가 새 데이터를 요청해야 하는 일반적인 경우입니다: - 콤보박스가 초기화될 때 - 콤보박스 목록을 스크롤할 때 - 새 콤보박스dataPreLoad와 함께 데이터를 방출virtualizationState 하여 원격 서비스에 새 요청을 할 수 있습니다. - 콤보박스에서 검색할 때 - 원격 결과를 필터링하기 위한 요청을 해야 합니다. - 콤보박스가 열리면 - 이전의 필터 작업을 모두 삭제해야 합니다.

    다음은 이미 정의된 작업을 수신하고 서버에 대한 요청을 실행하는 핸들러 목록입니다.

    import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
    import { IgxComboComponent } from 'igniteui-angular/combo';
    // import { IgxComboComponent } from '@infragistics/igniteui-angular'; for licensed package
    
    import { RemoteService } from '../../grid/services/remote.service';
    
    @Component({
        providers: [RemoteService],
        selector: 'app-combo-remote',
        styleUrls: ['./combo-remote.component.scss'],
        templateUrl: './combo-remote.component.html'
    })
    export class ComboRemoteComponent implements OnInit {
        @ViewChild('remoteCombo', { read: IgxComboComponent }) public remoteCombo: IgxComboComponent;
    
        public prevRequest: any;
        public rData: any;
    
        private searchText: string = null;
        private defaultVirtState: IForOfState = { chunkSize: 6, startIndex: 0 };
    
        private currentVirtState: IForOfState = { chunkSize: 6, startIndex: 0 };
        private itemID: number = 1;
        private itemCount: number = 0;
        private hasSelection: boolean;
        private additionalScroll: number = 0;
    
        constructor(private remoteService: RemoteService, public cdr: ChangeDetectorRef) { }
    
        public ngOnInit() {
            this.rData = this.remoteService.remoteData;
        }
    
        public ngAfterViewInit() {
            const initSize = {
                startIndex: 0,
                chunkSize: Math.ceil(250 / this.remoteCombo.itemHeight)
            };
            this.remoteService.getData(initSize, null, (data) => {
                this.remoteCombo.totalItemCount = data['@odata.count'];
                this.itemCount = this.remoteCombo.totalItemCount;
            });
        }
    
        public dataLoading(evt) {
            if (this.prevRequest) {
                this.prevRequest.unsubscribe();
            }
            this.prevRequest = this.remoteService.getData(
                this.remoteCombo.virtualizationState,
                this.searchText,
                (data) => {
                    this.remoteCombo.totalItemCount = data['@odata.count'];
                    this.cdr.detectChanges();
            });
        }
    
        public handleSearchInputUpdate(searchData: IComboSearchInputEventArgs) {
            this.currentVirtState.startIndex = 0;
            this.currentVirtState.chunkSize = Math.ceil(this.remoteCombo.itemsMaxHeight / this.remoteCombo.itemHeight);
            this.searchText = searchData?.searchText || '';
            this.remoteService.getData(
                this.searchText ? this.currentVirtState : this.defaultVirtState,
                this.searchText,
                (data) => {
                    this.remoteCombo.totalItemCount = data['@odata.count'];
                }
            );
        }
    
        public onOpened() {
            const scroll: number = this.remoteCombo.virtualScrollContainer.getScrollForIndex(this.itemID - 1);
            this.remoteCombo.virtualScrollContainer.scrollPosition = scroll + this.additionalScroll;
            this.cdr.detectChanges();
        }
    
        public onClosing() {
            this.searchText = '';
        }
    
        public onClosed() {
            this.currentVirtState.startIndex = (this.itemID || 1) - 1;
            this.remoteService.getData(
                this.currentVirtState,
                this.searchText,
                (data) => {
                    this.remoteCombo.totalItemCount = data['@odata.count'];
                    this.cdr.detectChanges();
                }
            );
        }
    
        public handleSelectionChanging(evt: IComboSelectionChangingEventArgs) {
            this.hasSelection = !!evt?.newSelection.length;
    
            if (!this.hasSelection) {
                this.itemID = 1;
                this.currentVirtState = this.defaultVirtState;
                return;
            }
    
            const currentSelection = evt.newSelection[evt.newSelection.length - 1]
            this.currentVirtState.chunkSize = Math.ceil(this.remoteCombo.itemsMaxHeight / this.remoteCombo.itemHeight);
    
            this.itemCount === currentSelection ?
                this.additionalScroll = this.remoteCombo.itemHeight :
                this.additionalScroll = 0;
    
            if (this.itemCount - currentSelection >= this.currentVirtState.chunkSize - 1) {
                this.itemID = this.currentVirtState.startIndex = currentSelection;
            } else {
                this.itemID = this.currentVirtState.startIndex = this.itemCount - (this.currentVirtState.chunkSize - 1);
            }
        }
    }
    
    Note

    새로운 데이터가 로드될 때마다 목록의 스크롤 바 크기를 적절히 만들기 위해 속성을 업데이트totalItemCount 합니다. 이 경우 서비스는 해당 속성을@odata.count 사용하여 총 크기를 반환합니다.

    Note

    서비스가 공급자로 포함되어야 합니다.

    Handling Selection

    청크로 로드된 원격 데이터에 묶인 콤보박스를 사용하고 더 복잡한 데이터 타입(예: 객체)을 다룰 때는 avalueKey. 콤보박스 주제에서 언급했듯이, 아니valueKey 오가 지정되면 콤보박스가 선택equality (===)을 처리하려고 합니다. 선택된 것으로 표시될 객체가 지속적으로 로드되는 객체와 동일하지 않으므로, 선택이 실패합니다.

    Note

    콤보박스를 원격 데이터에 바인딩할 때는 각 항목에 고유한 속성을 나타내는 avalueKey를 반드시 지정하세요.

    콤보박스가 원격 데이터에 바인딩되면 API를 통해 값/선택 항목을 설정하면 현재 청크에 로드된 항목만 고려됩니다. 초기값을 설정하려면 선택하기 전에 해당 특정 항목이 로드되었는지 확인하세요.

    API Summary

    Additional Resources

    우리 커뮤니티는 활동적이며 항상 새로운 아이디어를 환영합니다.