Edição e validação de grade Angular
A edição do Grid expõe um mecanismo de validação integrado da entrada do usuário ao editar células/linhas. Ele estende a funcionalidade de validação do Angular Form para permitir uma integração mais fácil com uma funcionalidade bem conhecida. Quando o estado do editor muda, indicadores visuais são aplicados à célula editada.
Configuração
Configure via template-driven configuration
Estendemos algumas das diretivas do validador do Angular Forms para trabalhar diretamente com oIgxColumn. Os mesmos validadores estão disponíveis como atributos a serem definidos declarativamente em.igx-column Os seguintes validadores são suportados de fábrica:
- obrigatório
- mínimo
- máx.
- comprimento mínimo
- comprimento máximo
- padrão
Para validar que uma entrada de coluna será definida e o valor será formatado como um e-mail, você pode usar as diretivas relacionadas:
<igx-column [field]="email" [header]="User E-mail" required email></igx-column>
O exemplo a seguir demonstra como usar as diretivas pré-construídasrequiredemail emin do validador em uma Grade.
Configure via reactive forms
Expomos oFormGroup que será usado para validação quando a edição começar em uma linha/célula via eventoformGroupCreated. Você pode modificá-lo adicionando seus próprios validadores para os campos relacionados:
<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());
}
Você pode decidir escrever sua própria função validadora ou usar uma das funções validadoras integradas Angular.
Validation service API
A grade expõe um serviço de validação via avalidation propriedade. Esse serviço possui as seguintes APIs públicas:
valid- retorna se o estado de validação da grade for válido.getInvalid- retorna registros com estados inválidos.clear- Libera o estado para registro por ID ou elimina todo o estado se nenhum ID for fornecido.markAsTouched- marca o registro/campo relacionado como tocado.
Os estados inválidos persistirão até que os erros de validação neles sejam corrigidos de acordo com a regra de validação ou sejam limpos.
Validation triggers
A validação será acionada nos seguintes cenários:
- Enquanto edita via o editor de células baseado na grade
validationTrigger. Ou ligadochangeenquanto digita no editor, ou quandobluro editor perde o foco ou fecha. - Ao atualizar células/linhas via API -
updateRow,updateCelletc. - Ao usar edição em lote e a/
undoredoAPI do serviço de transação.
Nota: A validação não será acionada para registros que não foram editados via entrada do usuário ou via API de edição. Indicadores visuais na célula só serão mostrados se a entrada relacionada for considerada tocada – seja por interação do usuário ou pela
markAsTouchedAPI do serviço de validação.
Angular Grid Validation Customization Options
Set a custom validator
Você pode definir sua própria diretriz de validação para usar no<igx-column> modelo.
@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;
}
}
Depois de definido e adicionado ao módulo do seu aplicativo, você pode defini-lo declarativamente para uma determinada coluna na grade:
<igx-column phoneFormat="\+\d{1}\-(?!0)(\d{3})\-(\d{3})\-(\d{4})\b" ...>
Change default error template
Você pode definir seu próprio modelo de erro personalizado que será exibido na dica de ferramenta de erro quando a célula entrar em estado inválido. Isso é útil em cenários em que você deseja adicionar sua própria mensagem de erro personalizada ou alterar a aparência ou o conteúdo da mensagem.
<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
Em alguns casos, você pode querer impedir o envio de um valor inválido nos dados. Nesses cenários, você pode usar oscellEdit eventos ourowEdit e cancelar o evento caso o novo valor seja inválido. Os argumentos de ambos os eventos têm umavalid propriedade e podem ser cancelados de acordo. Como ele é usado pode ser visto no exemplo de Validação Cruzada de Campo
<igx-grid (cellEdit)='cellEdit($event)' ...>
public cellEdit(evt) {
if (!evt.valid) {
evt.cancel = true;
}
}
Example
O exemplo abaixo demonstra as opções de personalização mencionadas acima.
Cross-field validation
Em alguns cenários, a validação de um campo pode depender do valor de outro campo no registro. Nesse caso, um validador personalizado pode ser usado para comparar os valores no registro via seu compartilhamentoFormGroup.
O exemplo abaixo demonstra uma validação de campo cruzado entre diferentes campos do mesmo registro. Ele verifica a validade das datas em comparação com a data atual e entre a data ativa e a data de criação do registro, bem como a proporção de negócios ganhos/perdidos para cada funcionário. Todos os erros são coletados em uma coluna fixada separada que mostra que o registro é inválido e exibe os erros relacionados.
As próximas linhas de código mostram a função validadora entre campos, que contém as comparações e define os erros relacionados a elas.
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;
}
O validador cross-field pode ser adicionado aoformGroup evento da linha de parteformGroupCreated, que retorna o novoformGroup para cada linha ao entrar no modo de edição:
<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());
}
Os diferentes erros são exibidos em uma célula modelo que combina todos os erros em uma única dica de ferramenta. Dependendo do estado válido da linha, um ícone diferente é exibido:
<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>
As mensagens de erro são reunidas nastateMessage função, que reúne os erros de cada célula, porque cada coluna pode ter validações de formulário com templates e então verifica os erros da própria linha, que vêm do customrowValidator.
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
O exemplo abaixo demonstra a validação entre campos em ação.
Estilização
Usando a Ignite UI for Angular, podemos alterar os estilos de validação padrão durante a edição.
No exemplo abaixo, faremos uso do modelo exposto para mensagem de validação, que aparece em uma dica de ferramenta e substitui a cor do erro para modificar a aparência padrão da validação. Também estilizaremos o plano de fundo das linhas inválidas para torná-las mais distintas.
Import theme
A maneira mais fácil de estilizar e acessar variáveis CSS é definir estilos noapp nosso arquivo de estilo global (normalmentestyles.scss). A primeira coisa que precisamos fazer é importar othemes/index arquivo – isso nos dá acesso a todas as ferramentas poderosas do framework Ignite UI for Angular Sass:
@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
Para mudar a cor de erro, você pode usar a variável--igx-error-500 css:
--igx-error-500: 34, 80%, 63%;
Custom Templates
Alterar o modelo de erro padrão permite definir classes e estilos personalizados:
<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
Linhas e células fornecem API para que os desenvolvedores saibam se uma linha ou célula é inválida e que tipo de erro está ativo.
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
| Limitação | Descrição |
|---|---|
QuandovalidationTrigger é borrão,editValue e a validação será acionada somente depois que o editor estiver desfocado. |
A razão é que isso utiliza o formControl'supdateOn propriedade. Isso determina o evento no qual o formControl atualizará e acionará validadores relacionados. |
Additional Resources
- Crie operações CRUD com igxGrid
- Visão geral da grade
- Edição de grade
- Edição de linha de grade
- Adição de linha de grade
- Transações de Grade