Angular 그리드 선택
Ignite UI for Angular 사용하면 다양한 이벤트, 풍부한 API 또는 단일 선택과 같은 간단한 마우스 상호 작용을 통해 데이터를 쉽게 선택할 수 있습니다.
Angular 그리드 선택 예제
아래 샘플은 세 가지 유형의 Grid 셀 선택 동작을 보여줍니다. 아래 버튼을 사용하여 사용 가능한 각 선택 모드를 활성화합니다. 스낵바 메시지 상자를 통해 각 버튼 상호작용에 대한 간략한 설명이 제공됩니다.
import { Component, ElementRef, OnInit, Renderer2, ViewChild } from '@angular/core' ;
import { GridSelectionMode, IgxGridComponent, IgxSnackbarComponent, IgxButtonGroupComponent, IgxColumnComponent, IgxButtonDirective, IgxIconComponent } from 'igniteui-angular' ;
import { DATA } from '../../data/nwindData' ;
import { IgxPreventDocumentScrollDirective } from '../../directives/prevent-scroll.directive' ;
@Component ({
selector : 'app-grid-cell-selection' ,
styleUrls : ['./grid-cellSelection.component.scss' ],
templateUrl : 'grid-cellSelection.component.html' ,
imports : [IgxButtonGroupComponent, IgxGridComponent, IgxPreventDocumentScrollDirective, IgxColumnComponent, IgxButtonDirective, IgxIconComponent, IgxSnackbarComponent]
})
export class GridCellSelectionComponent implements OnInit {
@ViewChild ('grid' , { static : true }) public grid: IgxGridComponent;
@ViewChild (IgxSnackbarComponent, { static : true }) public snackbar: IgxSnackbarComponent;
@ViewChild ('logger' ) public logger: ElementRef;
public data: any [];
public selection = true ;
public selectionMode: GridSelectionMode = 'multiple' ;
public selectionModes = [];
constructor (private renderer: Renderer2 ) { }
public ngOnInit(): void {
this .data = DATA;
this .selectionModes = [
{ label : 'none' , selected : this .selectionMode === 'none' , togglable : true },
{ label : 'single' , selected : this .selectionMode === 'single' , togglable : true },
{ label : 'multiple' , selected : this .selectionMode === 'multiple' , togglable : true }
];
this .snackbar.autoHide = false ;
this .snackbar.open();
}
public selectCellSelectionMode (args ) {
this .selectionMode = this .selectionModes[args.index].label;
this .snackbar.open();
}
public onRangeSelected ( ) {
const selectedData = JSON .stringify(this .grid.getSelectedData());
this .logAnEvent(`=> 'rangeSelected' with value: ` + selectedData);
}
public onCellSelected (event ) {
this .logAnEvent(`=> 'selected' with value: ` + event.cell.value);
}
public clearLog ( ) {
const elements = this .logger.nativeElement.querySelectorAll('p' );
for (let index = 0 ; index < elements.length; index++) {
this .renderer.removeChild(this .logger.nativeElement, elements[index]);
}
}
private logAnEvent (msg: string , canceled?: boolean ) {
const createElem = this .renderer.createElement('p' );
if (canceled) {
msg = msg.concat(': has been canceled ' );
}
const text = this .renderer.createText(msg);
this .renderer.appendChild(createElem, text);
const container = this .logger.nativeElement;
this .renderer.insertBefore(container, createElem, container.children[0 ]);
}
}
ts コピー <span class ="button-group-wrapper" >
<igx-buttongroup [values ]="selectionModes" (selected )="selectCellSelectionMode($event)" > </igx-buttongroup >
</span >
<div class ="sample-wrapper" >
<div class ="grid-wrapper" >
<igx-grid [igxPreventDocumentScroll ]="true" #grid [data ]="data" [height ]="'550px'" [cellSelection ]="selectionMode"
(rangeSelected )="onRangeSelected()"
(selected )="onCellSelected($event)"
>
<igx-column [field ]="'ProductID'" > </igx-column >
<igx-column [field ]="'ProductName'" > </igx-column >
<igx-column [field ]="'UnitsInStock'" [dataType ]="'number'" > </igx-column >
<igx-column [field ]="'UnitPrice'" [dataType ]="'number'" > </igx-column >
<igx-column [field ]="'Discontinued'" [dataType ]="'boolean'" >
</igx-column >
<igx-column [field ]="'OrderDate'" [dataType ]="'date'" > </igx-column >
</igx-grid >
</div >
<div class ="log-wrapper" >
<div class ="selected-data-area" >
<div class ="logContainer" >
<div class ="highlight" >
<span > Events execution sequence</span >
<button class ="clearBtn" igxButton ="flat" (click )="clearLog()" >
<igx-icon > clear</igx-icon >
<span > Clear log</span >
</button >
</div >
<hr />
<div #logger class ="logger" > </div >
</div >
</div >
</div >
</div >
<igx-snackbar #snackbar actionText ="Got it. Thanks!" (clicked )="snackbar.close()" >
<div class ="container" >
<igx-icon > notification_important</igx-icon >
@if (selectionMode === 'multiple') {
<ul >
<li > <b > This is the default selection behavior.</b > </li >
<li > Click on a cell and while pressing the mouse key perform drag action.
</li >
<li > Select a cell and press Shift + Arrow down key, this will start range selection as well.</li >
</ul >
}
@if (selectionMode === 'single') {
<ul >
<li > <b > Now you can select only one cell within the grid.</b > </li >
<li > On single cell click the previous selection state will be cleared.</li >
<li > The mouse drag will not work and instead of selecting a cell, this will make default text selection.</li >
</ul >
}
@if (selectionMode === 'none') {
<ul >
<li > <b > Now you are unable to select a cell while interacting with grid UI.</b > </li >
<li > If you need to select a cell, you can use the grid API methods.</li >
</ul >
}
</div >
</igx-snackbar >
html コピー :host {
width : 100% ;
}
.grid__wrapper {
display : flex;
justify-content : space-between;
margin : 16px ;
flex-flow : column;
align-items : flex-start;
position : relative;
}
.button-group-wrapper {
display : flex;
margin : 10px ;
}
.igx-snackbar {
background : rgba(0 , 0 , 0 , 0.7 );
}
.container {
display : flex;
igx-icon {
margin : 20px ;
}
}
.switches {
margin-top : 12px ;
margin-bottom : 8px ;
width : 100% ;
display : flex;
justify-content : space-around;
}
.sample-wrapper {
display : flex;
flex-flow : row wrap;
width : 100% ;
}
.grid-wrapper {
width : 60% ;
margin : 8px ;
}
.log-wrapper {
width : 35% ;
}
.clearBtn {
top : 3px ;
margin-left : 20px ;
}
.selected-data-area {
overflow-y : auto;
max-height : 550px ;
width : 100% ;
height : 100% ;
box-shadow : 0 1px 3px 0 rgba(0 , 0 , 0 , 0.2 ), 0 1px 1px 0 rgba(0 , 0 , 0 , 0.14 ), 0 2px 1px -1px rgba(0 , 0 , 0 , 0.12 );
margin-top : 8px ;
}
.logContainer {
padding : 0.2rem 0.4rem ;
}
.highlight {
text-align : center;
margin-bottom : 0.4rem ;
}
scss コピー
이 샘플이 마음에 드시나요? 전체 Ignite UI for Angular 툴킷에 액세스하고 몇 분 안에 나만의 앱을 구축해 보세요. 무료로 다운로드하세요.
Angular 그리드 선택 옵션
Angular Grid 구성 요소용 IgniteUI는 행 선택 , 셀 선택 및 열 선택 의 세 가지 다른 선택 모드를 제공합니다. 기본적으로 Grid에서는 다중 셀 선택 모드만 활성화됩니다. 선택 모드를 변경/활성화하려면 rowSelection
, cellSelection
또는 selectable
속성을 사용할 수 있습니다.
Angular 행 선택
rowSelection
속성을 사용하면 다음 옵션을 지정할 수 있습니다.
없음 - 그리드에 대한 행 선택이 비활성화됩니다.
Single - 그리드 내에서 하나의 행만 선택할 수 있습니다.
다중 - 행 Row selectors
사용하거나 Ctrl + 클릭 과 같은 키 조합을 사용하거나 셀에 초점을 맞춘 후 스페이스 키를 눌러 다중 행 선택을 사용할 수 있습니다.
자세한 내용은 행 선택 항목을 참조하세요.
Angular 셀 선택
속성 cellSelection
사용하면 다음 옵션을 지정할 수 있습니다.
없음 - 그리드에 대해 셀 선택이 비활성화됩니다.
단일 - 그리드 내에서 하나의 셀만 선택할 수 있습니다.
multiple - 현재 그리드 선택 항목의 기본 상태입니다. 다중 셀 선택은 마우스 왼쪽 버튼을 계속 클릭한 후 셀 위로 마우스를 드래그하여 선택할 수 있습니다.
자세한 내용은 셀 선택 항목을 참조하세요.
Angular 열 선택
selectable
속성을 사용하면 각 열에 대해 다음 옵션을 지정할 수 있습니다.
false - 그리드에 대해 해당 열 선택이 비활성화됩니다.
true - 해당 열 선택이 그리드에 대해 활성화됩니다.
이로 인해 다음 세 가지 변형이 발생합니다.
단일 선택 - 열 셀을 마우스로 클릭합니다 .
다중 열 선택 -Ctrl + 마우스를 누른 채 열 셀을 클릭합니다 .
범위 열 선택 -Shift 키를 누른 채 마우스를 클릭하면 그 사이의 모든 항목이 선택됩니다.
자세한 내용은 열 선택 항목 으로 이동하세요.
contextMenu
이벤트를 사용하면 사용자 정의 컨텍스트 메뉴를 추가하여 IgxGrid 작업을 용이하게 할 수 있습니다. 그리드 본체를 마우스 오른쪽 버튼으로 클릭 하면 이벤트가 트리거되는 셀을 방출합니다. 상황에 맞는 메뉴는 방출된 셀과 함께 작동합니다.
다중 셀 선택이 있는 경우 선택된 셀이 다중 셀 선택 영역에 있는지 확인하는 로직을 넣습니다. 그렇다면 선택한 셀의 값도 내보냅니다.
기본적으로 주요 기능은 다음과 같습니다.
public rightClick (eventArgs: any ) {
eventArgs.event.preventDefault();
this .multiCellArgs = {};
if (this .multiCellSelection) {
const node = eventArgs.cell.selectionNode;
const isCellWithinRange = this .grid1.getSelectedRanges().some(range => {
if (node.column >= range.columnStart &&
node.column <= range.columnEnd &&
node.row >= range.rowStart &&
node.row <= range.rowEnd) {
return true ;
}
return false ;
})
if (isCellWithinRange) {
this .multiCellArgs = { data : this .multiCellSelection.data };
}
}
this .contextmenuX = eventArgs.event.clientX;
this .contextmenuY = eventArgs.event.clientY;
this .clickedCell = eventArgs.cell;
this .contextmenu = true ;
}
typescript
상황에 맞는 메뉴에는 다음과 같은 기능이 있습니다.
선택한 셀의 값 복사
선택한 셀의 dataRow를 복사합니다.
선택한 셀이 다중 셀 선택 범위 내에 있는 경우 선택한 데이터를 모두 복사합니다.
public copySelectedCellData (event ) {
const selectedData = { [this .cell.column.field]: this .cell.value };
this .copyData(JSON .stringify({ [this .cell.column.field]: this .cell.value }));
this .onCellValueCopy.emit({ data : selectedData });
}
public copyRowData (event ) {
const selectedData = this .cell.row.data ;
this .copyData(JSON .stringify(this .cell.row.data));
this .onCellValueCopy.emit({ data : selectedData });
}
public copySelectedCells (event ) {
const selectedData = this .selectedCells.data;
this .copyData(JSON .stringify(selectedData));
this .onCellValueCopy.emit({ data : selectedData });
}
typescript
IgxGrid는 복사된 데이터를 가져와 컨테이너 요소에 붙여넣습니다.
그리드와 컨텍스트 메뉴를 결합하는 데 사용할 템플릿은 다음과 같습니다.
<div class ="wrapper" >
<div class ="grid__wrapper" (window:click )="disableContextMenu()" >
<igx-grid #grid1 [data ]="data" [autoGenerate ]="false" height ="500px" width ="100%"
(contextMenu )="rightClick($event)" (rangeSelected )="getCells($event)"
(selected )="cellSelection($event)" >
</igx-grid >
<div *ngIf ="contextmenu==true" >
<contextmenu [x ]="contextmenuX" [y ]="contextmenuY" [cell ]="clickedCell" [selectedCells ]="multiCellArgs" (onCellValueCopy )="copy($event)" >
</contextmenu >
</div >
</div >
<div class ="selected-data-area" >
<div >
<pre > {{copiedData}}</pre >
</div >
</div >
</div >
html
여러 셀을 선택하고 right mouse
버튼을 누릅니다. 상황에 맞는 메뉴가 나타나고 Copy cells data
선택하면 선택한 데이터가 오른쪽 빈 상자에 나타납니다. 결과는 다음과 같습니다.
import { Component, OnInit, ViewChild} from '@angular/core' ;
import { DefaultSortingStrategy, IgxGridComponent, SortingDirection, IgxColumnComponent, IgxCellTemplateDirective } from 'igniteui-angular' ;
import { DATA } from '../../data/nwindData' ;
import { IgxPreventDocumentScrollDirective } from '../../directives/prevent-scroll.directive' ;
import { ContextmenuComponent } from '.contextmenu/contextmenu.component' ;
@Component ({
selector : 'app-grid-contextmenu-sample' ,
styleUrls : ['./grid-contextmenu-sample.component.scss' ],
templateUrl : './grid-contextmenu-sample.component.html' ,
imports : [IgxGridComponent, IgxPreventDocumentScrollDirective, IgxColumnComponent, IgxCellTemplateDirective, ContextmenuComponent]
})
export class GridContextmenuSampleComponent implements OnInit {
@ViewChild ('grid1' , { read : IgxGridComponent, static : true })
public grid1: IgxGridComponent;
public data: any [];
public contextmenu = false ;
public contextmenuX = 0 ;
public contextmenuY = 0 ;
public clickedCell = null ;
public copiedData;
public multiCellSelection: { data : any []} = { data : []};
public multiCellArgs;
constructor ( ) {
}
public ngOnInit(): void {
this .data = DATA;
this .grid1.sortingExpressions = [
{
dir : SortingDirection.Asc, fieldName : 'ProductName' ,
ignoreCase : true , strategy : DefaultSortingStrategy.instance()
}
];
}
public formatDate (val: Date ) {
return new Intl .DateTimeFormat('en-US' ).format(val);
}
public rightClick (eventArgs: any ) {
eventArgs.event.preventDefault();
this .multiCellArgs = {};
if (this .multiCellSelection) {
const node = eventArgs.cell.selectionNode;
const isCellWithinRange = this .grid1.getSelectedRanges().some((range ) => {
if (node.column >= range.columnStart &&
node.column <= range.columnEnd &&
node.row >= range.rowStart &&
node.row <= range.rowEnd) {
return true ;
}
return false ;
});
if (isCellWithinRange) {
this .multiCellArgs = { data : this .multiCellSelection.data };
}
}
this .contextmenuX = eventArgs.event.clientX;
this .contextmenuY = eventArgs.event.clientY;
this .clickedCell = eventArgs.cell;
this .contextmenu = true ;
}
public disableContextMenu ( ) {
if (this .contextmenu) {
this .multiCellSelection = undefined ;
this .multiCellArgs = undefined ;
this .contextmenu = false ;
}
}
public getCells (event ) {
this .multiCellSelection = {
data : this .grid1.getSelectedData()
};
}
public copy (event ) {
this .copiedData = JSON .stringify(event.data, null , 2 );
if (this .multiCellSelection) {
this .multiCellSelection = undefined ;
this .multiCellArgs = undefined ;
this .grid1.clearCellSelection();
}
}
public cellSelection (event ) {
this .contextmenu = false ;
}
}
ts コピー <div class ="wrapper" >
<div class ="grid__wrapper" (window:click )="disableContextMenu()" >
<igx-grid [igxPreventDocumentScroll ]="true" #grid1 [data ]="data" [autoGenerate ]="false" height ="500px" width ="100%"
(contextMenu )="rightClick($event)" (rangeSelected )="getCells($event)"
(selected )="cellSelection($event)" >
<igx-column field ="ProductID" header ="Product ID" [headerClasses ]="'prodId'" >
</igx-column >
<igx-column field ="ProductName" header ="Product Name" [dataType ]="'string'" [sortable ]="true" >
</igx-column >
<igx-column field ="UnitsInStock" header ="UnitsInStock" dataType ="number" [sortable ]="true" >
<ng-template igxCell let-cell ="cell" let-val let-row >
${{val}}
</ng-template >
</igx-column >
<igx-column field ="OrderDate" [dataType ]="'date'" [formatter ]="formatDate" [sortable ]="true" >
</igx-column >
<igx-column field ="Discontinued" header ="Discontinued" [dataType ]="'boolean'" >
</igx-column >
</igx-grid >
@if (contextmenu) {
<div >
<app-contextmenu [x ]="contextmenuX" [y ]="contextmenuY" [cell ]="clickedCell" [selectedCells ]="multiCellArgs" (cellValueCopy )="copy($event)" >
</app-contextmenu >
</div >
}
</div >
<div class ="selected-data-area" >
<div >
<pre > {{copiedData}}</pre >
</div >
</div >
</div >
html コピー
.grid__wrapper {
width : 50% ;
}
.selected-data-area {
overflow-y : auto;
max-height : 500px ;
width : 50% ;
box-shadow : 0 1px 3px 0 rgba(0 , 0 , 0 , 0.2 ), 0 1px 1px 0 rgba(0 , 0 , 0 , 0.14 ), 0 2px 1px -1px rgba(0 , 0 , 0 , 0.12 );
margin-left : 10px ;
}
.wrapper {
margin : 10px ;
display : flex;
justify-content : space-evenly;
}
scss コピー
알려진 문제 및 제한 사항
IE11에서 선택이 활성화된 그리드를 사용하려면 각도 애플리케이션의 폴리필.ts에서 배열 폴리필을 명시적으로 가져와야 합니다. IE11은 버전 13.0.0부터 더 이상 지원되지 않습니다.
import 'core-js/es7/array' ;
typescript
그리드에 primaryKey
설정되지 않고 원격 데이터 시나리오가 활성화된 경우(그리드에 표시할 데이터를 검색하기 위해 원격 서버에 대한 페이징, 정렬, 필터링, 스크롤 트리거 요청 시) 행은 데이터 이후 다음 상태를 잃게 됩니다. 요청이 완료되었습니다:
API 참조
추가 리소스
우리 커뮤니티는 활동적이며 항상 새로운 아이디어를 환영합니다.