Angular 그리드 편집 및 검증

    그리드의 편집은 셀/행을 편집할 때 사용자 입력에 대한 내장된 유효성 검사 메커니즘을 노출합니다. 잘 알려진 기능과 더 쉽게 통합할 수 있도록 Angular Form 유효성 검사 기능을 확장합니다. 편집기 상태가 변경되면 편집된 셀에 시각적 표시가 적용됩니다.

    구성

    Configure via template-driven configuration

    IgxColumn과 직접 작동하도록 Angular Forms 유효성 검사기 지시문 중 일부를 확장합니다. igx-column에서 선언적으로 설정할 속성으로 동일한 유효성 검사기를 사용할 수 있습니다. 기본적으로 지원되는 유효성 검사기는 다음과 같습니다.

    • 필수의
    • 최대
    • 이메일
    • 최소 길이
    • 최대 길이
    • 무늬

    열 입력이 설정되고 값이 이메일 형식으로 지정되는지 확인하려면 관련 지시문을 사용할 수 있습니다.

    <igx-column [field]="email" [header]="User E-mail" required email></igx-column>
    

    다음 샘플은 그리드에서 사전 구축된 required, emailmin 유효성 검사기 지시문을 사용하는 방법을 보여줍니다.

    Configure via reactive forms

    formGroupCreated 이벤트를 통해 행/셀에서 편집을 시작할 때 유효성 검사에 사용될 FormGroup 노출합니다. 관련 필드에 대한 자체 유효성 검사기를 추가하여 수정할 수 있습니다.

    <igx-grid (formGroupCreated)='formCreateHandler($event)' ...>
    
        public formCreateHandler(args: IGridFormGroupCreatedEventArgs) {
            const formGroup = args.formGroup;
            const orderDateRecord = formGroup.get('OrderDate');
            const requiredDateRecord = formGroup.get('RequiredDate');
            const shippedDateRecord = formGroup.get('ShippedDate');
    
            orderDateRecord.addValidators(this.futureDateValidator());
            requiredDateRecord.addValidators(this.pastDateValidator());
            shippedDateRecord.addValidators(this.pastDateValidator());
        }
    

    자신만의 유효성 검사기 함수를 작성하거나 내장된 Angular 유효성 검사기 함수 중 하나를 사용할 수 있습니다.

    Validation service API

    그리드는 validation 속성을 통해 유효성 검사 서비스를 노출합니다. 해당 서비스에는 다음과 같은 공개 API가 있습니다.

    • valid- 그리드 유효성 검사 상태가 유효한지 여부를 반환합니다.
    • getInvalid- 잘못된 상태의 레코드를 반환합니다.
    • clear- ID별로 기록할 상태를 지우거나 ID가 제공되지 않은 경우 모든 상태를 지웁니다.
    • markAsTouched- 관련 레코드/필드를 터치된 것으로 표시합니다.

    유효하지 않은 상태는 유효성 검사 오류가 유효성 검사 규칙에 따라 수정되거나 지워질 때까지 지속됩니다.

    Validation triggers

    유효성 검사는 다음 시나리오에서 트리거됩니다.

    • 그리드의 validationTrigger 기반으로 셀 편집기를 통해 편집하는 동안. 편집기에서 입력하는 동안 change 되거나 편집기가 초점을 잃거나 닫힐 때 blur 발생합니다.
    • API(updateRow, updateCell 등)를 통해 셀/행을 업데이트하는 경우.
    • 일괄 편집 및 트랜잭션 서비스의 undo / redo API를 사용할 때.

    참고: 사용자 입력이나 편집 API를 통해 편집되지 않은 레코드에 대해서는 유효성 검사가 트리거되지 않습니다. 셀의 시각적 표시기는 사용자 상호 작용이나 유효성 검사 서비스의 markAsTouched API를 통해 관련 입력이 터치된 것으로 간주되는 경우에만 표시됩니다.

    Angular Grid Validation Customization Options

    Set a custom validator

    템플릿의 <igx-column>에 사용할 자체 유효성 검사 지시문을 정의할 수 있습니다.

    @Directive({
        selector: '[phoneFormat]',
        providers: [{ provide: NG_VALIDATORS, useExisting: PhoneFormatDirective, multi: true }]
    })
    export class PhoneFormatDirective extends Validators {
        @Input('phoneFormat')
        public phoneFormatString = '';
    
        public validate(control: AbstractControl): ValidationErrors | null {
            return this.phoneFormatString ? phoneFormatValidator(new RegExp(this.phoneFormatString, 'i'))(control)
                : null;
        }
    }
    

    앱 모듈에 정의되고 추가되면 그리드의 지정된 열에 선언적으로 설정할 수 있습니다.

    <igx-column phoneFormat="\+\d{1}\-(?!0)(\d{3})\-(\d{3})\-(\d{4})\b" ...>
    

    Change default error template

    셀이 잘못된 상태에 들어갈 때 오류 도구 설명에 표시될 고유한 사용자 정의 오류 템플릿을 정의할 수 있습니다. 이는 사용자 정의 오류 메시지를 추가하거나 메시지의 모양이나 내용을 변경하려는 시나리오에서 유용합니다.

    <igx-column ... >
      <ng-template igxCellValidationError let-cell='cell' let-defaultErr="defaultErrorTemplate">
          <ng-container *ngTemplateOutlet="defaultErr">
          </ng-container>
          <div *ngIf="cell.validation.errors?.['phoneFormat']">
            Please enter correct phone format
          </div>
      </ng-template>
    </igx-column>
    

    Prevent exiting edit mode on invalid state

    어떤 경우에는 데이터에 유효하지 않은 값을 제출하는 것을 허용하지 않을 수도 있습니다. 해당 시나리오에서는 cellEdit 또는 rowEdit 이벤트를 사용하고 새 값이 유효하지 않은 경우 이벤트를 취소할 수 있습니다. 두 이벤트의 인수 모두 valid 속성을 가지며 이에 따라 취소될 수 있습니다. 사용 방법은 Cross-field Validation 예제에서 확인할 수 있습니다.

    <igx-grid (cellEdit)='cellEdit($event)' ...>
    
    public cellEdit(evt) {
      if (!evt.valid) {
        evt.cancel = true;
      }
    }
    

    Example

    아래 예에서는 위에서 언급한 사용자 정의 옵션을 보여줍니다.

    Cross-field validation

    일부 시나리오에서는 한 필드의 유효성 검사가 레코드의 다른 필드 값에 따라 달라질 수 있습니다. 이 경우 사용자 정의 유효성 검사기를 사용하여 공유 FormGroup 통해 레코드의 값을 비교할 수 있습니다.

    아래 샘플은 동일한 레코드의 서로 다른 필드 간의 필드 간 유효성 검사를 보여줍니다. 현재 날짜와 비교하여 날짜 유효성을 확인하고 기록 날짜의 활성 날짜와 생성 날짜 사이의 날짜 유효성과 각 직원의 거래 성패 비율을 확인합니다. 모든 오류는 레코드가 유효하지 않음을 보여주고 관련 오류를 표시하는 별도의 고정 열에 수집됩니다.

    다음 코드 줄은 비교를 포함하고 그에 관련된 관련 오류를 설정하는 교차 필드 유효성 검사 기능을 보여줍니다.

    private rowValidator(): ValidatorFn {
        return (formGroup: FormGroup): ValidationErrors | null => {
            let returnObject = {};
            const createdOnRecord = formGroup.get('created_on');
            const lastActiveRecord = formGroup.get('last_activity');
            const winControl = formGroup.get('deals_won');
            const loseControl = formGroup.get('deals_lost');
            const actualSalesControl = formGroup.get('actual_sales');
    
            // Validate dates
            const curDate = new Date();
            if (new Date(createdOnRecord.value) > curDate) {
                // The created on date shouldn't be greater than current date.
                returnObject['createdInvalid'] =  true;
            }
            if (new Date(lastActiveRecord.value) > curDate) {
                // The last active date shouldn't be greater than current date.
                returnObject['lastActiveInvalid'] = true;
            }
            if (new Date(createdOnRecord.value) > new Date(lastActiveRecord.value)) {
                // The created on date shouldn't be greater than last active date.
                returnObject['createdLastActiveInvalid'] = true;
            }
            
            // Validate deals
            const dealsRatio = this.calculateDealsRatio(winControl.value, loseControl.value);
            if (actualSalesControl.value === 0 && dealsRatio > 0) {
                // If the actual sales value is 0 but there are deals made.
                returnObject['salesZero'] = true;
            }
            if (actualSalesControl.value > 0 && dealsRatio === 0) {
                // If the deals ratio based on deals won is 0 but the actual sales is bigger than 0.
                returnObject['salesNotZero'] = true;
            }
            
            return returnObject;
        };
    }
    
    public calculateDealsRatio(dealsWon, dealsLost) {
        if (dealsLost === 0) return dealsWon + 1;
        return Math.round(dealsWon / dealsLost * 100) / 100;
    }
    

    교차 필드 유효성 검사기를 formGroup 행의 formGroupCreated 새로운 것을 반환하는 이벤트 formGroup 편집 모드에 들어갈 때 각 행에 대해:

    <igx-grid #grid1 [data]="transactionData" [width]="'100%'" [height]="'480px'" [autoGenerate]="false" 
            [batchEditing]="true" [rowEditable]="true" [primaryKey]="'id'"
            (formGroupCreated)='formCreateHandler($event)'>
        <!-- ... -->
    </igx-grid>
    
    
    public formCreateHandler(evt: IGridFormGroupCreatedEventArgs) {
        evt.formGroup.addValidators(this.rowValidator());
    }
    

    다양한 오류는 모든 오류를 단일 도구 설명에 결합하는 템플릿 셀에 표시됩니다. 행의 유효한 상태에 따라 다른 아이콘이 표시됩니다.

    <igx-column field="row_valid" header=" " [editable]="false" [pinned]="true" [width]="'50px'">
        <ng-template igxCell let-cell="cell">
            <div *ngIf="isRowValid(cell)" [igxTooltipTarget]="tooltipRef"  style="margin-right: '-10px';">
                <img width="18" src="assets/images/grid/active.png"/>
            </div>
            <div *ngIf="!isRowValid(cell)" [igxTooltipTarget]="tooltipRef" style="margin-right: '-10px';">
                <img width="18" src="assets/images/grid/expired.png"/>
            </div>
            <div #tooltipRef="tooltip" igxTooltip [style.width]="'max-content'">
                <div *ngFor="let message of stateMessage(cell)">
                    {{message}}
                </div>
            </div>
        </ng-template>
    </igx-column>
    

    오류 메시지는 각 셀에 대한 오류를 수집하는 stateMessage 함수에서 수집됩니다. 왜냐하면 각 열에는 템플릿 양식 유효성 검사가 있을 수 있고 사용자 정의 rowValidator에서 오는 행 자체에 대한 오류를 확인할 수 있기 때문입니다.

    public stateMessage(cell: CellType) {
        const messages = [];
        const row = cell.row;
        const cellValidationErrors = row.cells.filter(x => !!x.validation.errors);
        cellValidationErrors.forEach(cell => {
            if (cell.validation.errors) {
                if (cell.validation.errors.required) {
                    messages.push(`The \`${cell.column.header}\` column is required.`);
                }
                // Other cell errors ...
            }
        });
    
        if (row.validation.errors?.createdInvalid) {
            messages.push(`The \`Date of Registration\` date cannot be in the future.`);
        }
        // Other cross-field errors...
    
        return messages;
    }
    
    

    Cross-field example

    아래 샘플은 실제 크로스 필드 유효성 검사를 보여줍니다.

    스타일링

    Ignite UI for Angular 사용하면 편집하는 동안 기본 유효성 검사 스타일을 변경할 수 있습니다.

    아래 예에서는 도구 설명에 표시되는 유효성 검사 메시지에 대해 노출된 템플릿을 사용하고 오류 색상을 재정의하여 유효성 검사의 기본 모양을 수정합니다. 또한 유효하지 않은 행의 배경 스타일을 지정하여 더욱 뚜렷하게 만듭니다.

    Import theme

    CSS 변수에 스타일을 지정하고 액세스하는 가장 쉬운 방법은 app의 전역 스타일 파일(일반적으로 styles.scss)에서 스타일을 정의하는 것입니다. 가장 먼저 해야 할 일은 themes/index 파일을 가져오는 것입니다. 이를 통해 Ignite UI for Angular의 모든 강력한 도구에 액세스할 수 있습니다.

    @use "igniteui-angular/theming" as *;
    
    // IMPORTANT: Prior to Ignite UI for Angular version 13 use:
    // @import '~igniteui-angular/lib/core/styles/themes/index';
    

    Include the styles

    오류 색상을 변경하려면 CSS 변수--igx-error-500 사용할 수 있습니다.

    --igx-error-500: 34, 80%, 63%;
    

    Custom Templates

    기본 오류 템플릿을 변경하면 사용자 정의 클래스와 스타일을 설정할 수 있습니다.

    <ng-template igxCellValidationError let-cell='cell' let-defaultErr='defaultErrorTemplate'>
        <div class="validator-container">
            <ng-container *ngTemplateOutlet="defaultErr">
            </ng-container>
        </div>
    </ng-template>
    

    Invalid row and cell styles

    행과 셀은 개발자가 행이나 셀이 유효하지 않은지, 어떤 종류의 오류가 활성화되어 있는지 알 수 있는 API를 제공합니다.

    public rowStyles = {
        background: (row: RowType) => row.validation.status === 'INVALID' ? '#FF000033' : '#00000000'
    };
    public cellStyles = {
        'invalid-cell': (rowData, columnKey) => {
            const pKey = this.grid.primaryKey;
            const cell = this.grid.getCellByKey(rowData[pKey], columnKey);
            return cell && cell.validation.status === 'INVALID';
        }
    }
    
    <igx-grid [rowStyles]="rowStyles">
        <igx-column field="ReorderLevel" header="ReorderLever" required [cellClasses]="cellStyles">
    

    Demo

    API References

    Known Issues and Limitations

    한정 설명
    언제validationTrigger 흐릿하다,editValue 유효성 검사는 편집기가 흐려진 후에만 실행됩니다. 이유는 이것이 formControl의updateOn 재산. 이는 formControl이 관련 유효성 검사기를 업데이트하고 트리거하는 이벤트를 결정합니다.

    Additional Resources

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