J'essayais de modifier la validation FormGroup du FormGroup attribué à une grille Kendo lorsque l'un des éléments du dataItem est modifié. La logique est que : Si le type d'authentification sélectionné est de base, le nom d'utilisateur et le mot de passe doivent être « requis » par la validation du formulaire.
Si le AuthType sélectionné est QueryString, queryString doit être « requis » par la validation du formulaire. Si l'AuthType sélectionné est AuthorizationHeader, l'authorizationHeader doit être « requis » par la validation du formulaire.

Ce problème était, après la mise à jour du FormGroup, la validation ne semble plus fonctionner correctement. Les anciennes validations sont toujours honorées, et lorsque la sélection du AuthType est modifiée, les validations des champs désormais masqués empêchent alors la soumission du formulaire.

Il est mon code : web-connections.component.ts :

import { Component, OnInit } from '@angular/core';
import { ConnectionService } from '../connections.service';
import { SourceTypeService } from '../source-type-selector/source-type.service';
import { DialogSettings, DialogService, DialogAction } from '@progress/kendo-angular-dialog';
import { CategoryService } from 'src/app/category/category.service';
import { FormGroup, FormControl, Validators } from '@angular/forms';

@Component({
  selector: 'web-connections',
  templateUrl: './web-connections.component.html',
  styleUrls: ['./web-connections.component.css']
})
export class WebConnectionsComponent {
  webConnections = [];
  itemBeingEdited = {};
  editedRowIndex = 0;
  editedConnection = {};
  filteredWebConnections: any[];
  formGroup: FormGroup;

  selectedSourceType;
  selectedCategory: any;

  WEBAuthorizationEnum = [
    {name: "None", value:0},
    {name: "Basic", value:1},
    {name: "QueryString", value:2},
    {name: "AuthorizationHeader", value:3}
  ]

  subscriptions = [];
  constructor(private service: ConnectionService, 
    private sourceTypeService: SourceTypeService,
    private categoryService: CategoryService,
    private dialogService: DialogService) {
    this.subscriptions.push(this.sourceTypeService.selectedSourceType.subscribe(x => {
      this.selectedSourceType = x;
      this.UpdateData();
    }));
    this.subscriptions.push(this.categoryService.selectedCategory.subscribe(x => {
      this.selectedCategory = x;
      this.UpdateData();
    }));
    this.subscriptions.push(this.service.connections.subscribe(c => {
      this.webConnections = c.filter(x => x && x.sourceTypeID == 2);  
      this.UpdateData();    
    }));
  }

  ngOnDestroy(): void {
    this.subscriptions.forEach(x => x.unsubscribe());
  }

  AuthType(authType) {
    return this.WEBAuthorizationEnum[authType].name;
  }

  UpdateData() {
    if (this.webConnections != null && this.selectedCategory != null) {
      this.filteredWebConnections = this.webConnections.filter(x => x.categoryID == this.selectedCategory.categoryID);
    }
  }

  ngAfterViewInit() {
    this.service.RefreshIfOld();
  }

  public addHandler({sender}) {
    this.closeEditor(sender);
    this.formGroup = this.createFormGroup({});
    sender.addRow(this.formGroup);
  }

  public editHandler({sender, rowIndex, dataItem}) {
    this.closeEditor(sender);
    this.itemBeingEdited = {...dataItem};
    this.editedRowIndex = rowIndex;
    this.editedConnection = Object.assign({}, dataItem);
    this.formGroup = this.createFormGroup(dataItem);
    sender.editRow(rowIndex, this.formGroup);
  }

  public cancelHandler({sender, rowIndex}) {
    this.closeEditor(sender, rowIndex);
  }

  grid;
  private closeEditor(grid, rowIndex = this.editedRowIndex) {
    grid.closeRow(rowIndex);
    this.resetItem(this.editedConnection);
    this.editedRowIndex = undefined;
    this.editedConnection = undefined;
  }


  public saveHandler({sender, rowIndex, formGroup, isNew}) {
    this.service.save(formGroup.value, isNew);
    sender.closeRow(rowIndex);
  }

  public resetItem(item) {
    item = {...this.itemBeingEdited};
  }

  public removeHandler({dataItem}) {
    var dialog = new DialogSettings();
    dialog.title = 'Confirm Delete';
    dialog.content =  "Are you sure you want to delete?  Deleting a Connection will ALL DATA that is currently associated with it. (Requests, DataMaps, Jobs, etc).";
    var actionYes = new DialogAction();
    actionYes.primary = true;
    actionYes.text = "Yes";
    var actionNo = new DialogAction();
    actionNo.primary = false;
    actionNo.text = "No";
    dialog.actions = [actionYes, actionNo];
    this.dialogService.open(dialog).result.subscribe((actionResult : any) => {
      if (actionResult.text == "Yes") {
        this.service.remove(dataItem);
      }
    });
  }

  fieldForEdit;
  fieldForEditValue;
  showExpressionEditor = false;
  openEditorDialog(fieldName) {
    this.fieldForEdit = fieldName;
    this.fieldForEditValue = this.formGroup.get(this.fieldForEdit).value;
    this.showExpressionEditor = true;
  }

  updateFieldForEdit(value) {
    this.formGroup.get(this.fieldForEdit).setValue(value);
    this.fieldForEdit = undefined;
    this.fieldForEditValue = undefined;
  }

  resetValidators() {    
    this.formGroup.controls['username'].clearValidators();
    this.formGroup.controls['username'].setErrors(null);
    this.formGroup.controls['username'].setValue(null);
    this.formGroup.controls['password'].clearValidators();
    this.formGroup.controls['password'].setErrors(null);
    this.formGroup.controls['password'].setValue(null);
    this.formGroup.controls['queryString'].clearValidators();
    this.formGroup.controls['queryString'].setErrors(null);
    this.formGroup.controls['queryString'].setValue(null);
    this.formGroup.controls['authorizationHeader'].clearValidators();
    this.formGroup.controls['authorizationHeader'].setErrors(null);
    this.formGroup.controls['authorizationHeader'].setValue(null);
    if (this.formGroup.get('authType').value == 1) {
      this.formGroup.controls['username'].setValidators(Validators.required);
      this.formGroup.controls['password'].setValidators(Validators.required);
    }
    if (this.formGroup.get('authType').value == 2) {
      this.formGroup.controls['queryString'].setValidators(Validators.required);
    }
    if (this.formGroup.get('authType').value == 3) {
      this.formGroup.controls['authorizationHeader'].setValidators(Validators.required);
    }    
    this.formGroup.controls['username'].updateValueAndValidity();
    this.formGroup.controls['password'].updateValueAndValidity();
    this.formGroup.controls['queryString'].updateValueAndValidity();
    this.formGroup.controls['authorizationHeader'].updateValueAndValidity();
    this.formGroup.updateValueAndValidity();
  }

  createFormGroup = dataItem => new FormGroup({
    "uri":new FormControl(dataItem.uri, Validators.required),
    "name": new FormControl(dataItem.name, Validators.required),
    "authType": new FormControl(dataItem.authType, Validators.required),
    "username": new FormControl(dataItem.username),
    "password": new FormControl(dataItem.password),
    "queryString": new FormControl(dataItem.queryString),
    "authorizationHeader": new FormControl(dataItem.authorizationHeader),
    "sourceTypeID": new FormControl(this.selectedSourceType.sourceTypeID),
    "categoryID": new FormControl(this.selectedCategory.categoryID)
  });
}

Connexions-web.component.html

<expression-editor-dialog *ngIf="showExpressionEditor == true" [(show)]="showExpressionEditor"
  [expression]="fieldForEditValue" (expressionChange)="updateFieldForEdit($event)"></expression-editor-dialog>

<kendo-grid [data]="filteredWebConnections" [height]="400" (edit)="editHandler($event)" (cancel)="cancelHandler($event)"
  (save)="saveHandler($event)" (remove)="removeHandler($event)" (add)="addHandler($event)">
  <ng-template kendoGridToolbarTemplate>
    <button kendoGridAddCommand title="Add {{selectedSourceType? selectedSourceType.description : ''}} Connection"
      icon="plus" [primary]="true">Add {{selectedTab}} Connection</button>
  </ng-template>
  <kendo-grid-column field="uri" title="API URI" width="280"></kendo-grid-column>
  <kendo-grid-column field="name" title="Name" width="200"></kendo-grid-column>
  <kendo-grid-column field="authType" title="Auth Type" width="150">
    <ng-template kendoGridEditTemplate let-dataItem="dataItem" >
      <kendo-dropdownlist [data]="WEBAuthorizationEnum" (selectionChange)="resetValidators()" [popupSettings]="{width: 280}" textField="name"
        valueField="value" valuePrimitive="true" name="authType" [formControl]="formGroup?.get('authType')"></kendo-dropdownlist>
    </ng-template>
    <ng-template kendoGridCellTemplate let-dataItem="dataItem">
      {{AuthType(dataItem.authType)}}
    </ng-template>
  </kendo-grid-column>
  <kendo-grid-column field="username" title="Username" width="150">
    <ng-template kendoGridEditTemplate let-dataItem="dataItem"  let-column="column" >
      <input [hidden]="dataItem.authType != 1" placeholder="Username" kendoTextBox [formControl]="formGroup?.get(column.field)"
        name="username"/>
    </ng-template>
  </kendo-grid-column>
  <kendo-grid-column field="password" title="Password" width="150">
    <ng-template kendoGridEditTemplate let-dataItem="dataItem" let-column="column">
      <input [hidden]="dataItem.authType != 1" placeholder="Password" kendoTextBox [formControl]="formGroup?.get(column.field)"
        name="password"/>
    </ng-template>
    <ng-template kendoGridCellTemplate let-dataItem="dataItem">
      <span *ngIf="dataItem.password != null">*******</span>
    </ng-template>
  </kendo-grid-column>
  <kendo-grid-column field="queryString" title="Query String" width="150">
    <ng-template kendoGridEditTemplate let-dataItem="dataItem"  let-column="column">
      <input [hidden]="dataItem.authType != 2" placeholder="Query String" kendoTextBox [formControl]="formGroup?.get(column.field)"
        name="queryString" class="withButton"/>
      <button [hidden]="dataItem.authType != 2" class="withInput" kendoButton title="Edit With Expression Editor" icon="pencil"
        (click)="openEditorDialog('queryString')"></button>
    </ng-template>
  </kendo-grid-column>
  <kendo-grid-column field="authorizationHeader" title="Authorization Header" width="150">
    <ng-template kendoGridEditTemplate let-dataItem="dataItem"  let-column="column">
      <input [hidden]="dataItem.authType != 3" placeholder="Authorization Header" kendoTextBox
      [formControl]="formGroup?.get(column.field)" name="authorizationHeader" class="withButton"/>
      <button [hidden]="dataItem.authType != 3" kendoButton title="Edit With Expression Editor" class="withInput" icon="pencil"
        (click)="openEditorDialog('authorizationHeader')"></button>
    </ng-template>
  </kendo-grid-column>
  <kendo-grid-command-column autoSize="false" width="78">
    <ng-template kendoGridCellTemplate  let-isNew="isNew">
      <button kendoGridEditCommand [primary]="true" icon="pencil"></button>
      <button kendoGridRemoveCommand icon="trash"></button>
      <button [title]="isNew ? 'Add' : 'Update'" kendoGridSaveCommand [primary]="true" icon="floppy" [disabled]="formGroup?.invalid"></button>
      <button [title]="isNew ? 'Discard' : 'Cancel'" kendoGridCancelCommand icon="cancel"></button>
    </ng-template>
  </kendo-grid-command-column>
</kendo-grid>

0
Trent 25 janv. 2020 à 00:30

1 réponse

Meilleure réponse

Donc, il s'avère que j'ai fini par trouver la solution à mon propre problème.

La solution implémentait un validateur personnalisé pour les fonctions qui devaient avoir une validation qui réagissait à son propre dataItem.

J'ai également dû implémenter un peu de code dans la sélection enum pour définir la valeur FormGroup de authType et déclencher la validation initiale des champs validés personnalisés et réinitialiser toutes les valeurs existantes dans ces champs.

Voir la solution ci-dessous :

Dans composant.html :

<kendo-grid-column field="authType" title="Auth Type" width="150">
    <ng-template kendoGridEditTemplate let-dataItem="dataItem" >
      <kendo-dropdownlist [data]="WEBAuthorizationEnum" (selectionChange)="resetValidators($event)" [popupSettings]="{width: 280}" textField="name"
        valueField="value" valuePrimitive="true" name="authType" [formControl]="formGroup?.get('authType')"></kendo-dropdownlist>
    </ng-template>
    <ng-template kendoGridCellTemplate let-dataItem="dataItem">
      {{AuthType(dataItem.authType)}}
    </ng-template>
  </kendo-grid-column>

Dans component.ts:

requiredIfAuthType = (authType: number) => (control: AbstractControl) =>  {
    if (this.formGroup && this.formGroup.controls && this.formGroup.controls.authType && this.formGroup.controls.authType.value) {
      if (this.formGroup.controls.authType.value == authType && (!control.value || control.value == "")) {
        return {required: true};
      }
    }
    return null;
  }

  resetValidators(authType) {
    this.formGroup.controls.authType.setValue(authType.value);
    this.formGroup.controls.username.reset();
    this.formGroup.controls.password.reset();
    this.formGroup.controls.queryString.reset();
    this.formGroup.controls.authorizationHeader.reset();
    this.formGroup.controls.username.updateValueAndValidity();
    this.formGroup.controls.password.updateValueAndValidity();
    this.formGroup.controls.queryString.updateValueAndValidity();
    this.formGroup.controls.authorizationHeader.updateValueAndValidity();
  }


  createFormGroup = dataItem => new FormGroup({
    "uri":new FormControl(dataItem.uri, Validators.required),
    "name": new FormControl(dataItem.name, Validators.required),
    "authType": new FormControl(dataItem.authType, Validators.required),
    "username": new FormControl(dataItem.username, this.requiredIfAuthType(1)),
    "password": new FormControl(dataItem.password, this.requiredIfAuthType(1)),
    "queryString": new FormControl(dataItem.queryString, this.requiredIfAuthType(2)),
    "authorizationHeader": new FormControl(dataItem.authorizationHeader, this.requiredIfAuthType(3)),
    "sourceTypeID": new FormControl(this.selectedSourceType.sourceTypeID),
    "categoryID": new FormControl(this.selectedCategory.categoryID),
  });

Merci!

0
Trent 27 janv. 2020 à 18:49