如何验证同一级别的2个文件夹在递归Angular形式数组中不能具有相同的名称

问题描述 投票:0回答:1

我不确定我的问题标题是否足够清楚,但我会尽力提供更多细节。我尝试使用角度形式创建文件夹层次结构形式。表单可以无限嵌套。我的问题是,现在我可以在某个级别添加 2 个具有相同名称的文件夹,但这应该是不可能的,并且应该警告用户。这是合乎逻辑的,因为在普通文件系统中,2 个文件夹不能具有相同的名称

为了清楚起见,我在这里提供一个简化版本。阅读起来还是有点长,但是这里有可重现的演示在 stackblitz 中具有相同的代码

表单组件

@Component({
  selector: 'my-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.css'],
})
export class FormComponent implements OnInit {
  myForm!: FormGroup;
  isHierarchyVisible: boolean = false;

  constructor(private formBuilder: FormBuilder) {}

  ngOnInit() {
    this.myForm = this.formBuilder.group({
      folderHierarchy: this.formBuilder.array([]),
    });
    if (this.folderHierarchy.length === 0) this.isHierarchyVisible = false;
  }

  removeFolder(index: number): void {
    this.folderHierarchy.removeAt(index);
    if (this.folderHierarchy.length === 0) this.isHierarchyVisible = false;
  }

  addFolder(): void {
    this.folderHierarchy.push(
      this.formBuilder.group({
        name: [null, [Validators.required]],
        subFolders: this.formBuilder.array([]),
        level: 0,
      })
    );
    this.isHierarchyVisible = true;
  }

  getForm(control: AbstractControl): FormGroup {
    return control as FormGroup;
  }

  get folderHierarchy(): FormArray {
    return this.myForm.get('folderHierarchy') as FormArray;
  }
}
<p>folder form. type in form name and press enter</p>
<form [formGroup]="myForm">
  <div formArrayName="folderHierarchy">
    <label for="folderHierarchy">create folder</label>
    <div>
      <button type="button" class="btn btn-custom rounded-corners btn-circle mb-2" (click)="addFolder()" [disabled]="!folderHierarchy.valid">
        Add
      </button>
      <span class="pl-1">new folder</span>
    </div>
    <div>
      <div *ngIf="!folderHierarchy.valid" class="folder-hierarchy-error">invalid folder hierarchy</div>
      <div class="folderContainer">
        <div>
          <div *ngFor="let folder of folderHierarchy.controls; let i = index" [formGroupName]="i">
            <folder-hierarchy (remove)="removeFolder(i)" [folder]="getForm(folder)" [index]="i"></folder-hierarchy>
          </div>
        </div>
      </div>
    </div>
  </div>
</form>

文件夹层次结构组件

@Component({
  selector: 'folder-hierarchy',
  templateUrl: './folder-hierarchy.component.html',
  styleUrls: ['./folder-hierarchy.component.css'],
})
export class FolderHierarchyComponent implements OnInit {
  constructor(private formBuilder: FormBuilder) {}
  @Output() remove = new EventEmitter();
  @Input() folder!: FormGroup;
  @Input() index!: number;
  tempName: string = '';

  ngOnInit() {}

  addSubFolder(folder: FormGroup): void {
    (folder.get('subFolders') as FormArray).push(
      this.formBuilder.group({
        name: [null, [Validators.required]],
        subFolders: this.formBuilder.array([]),
        level: folder.value.level + 1,
      })
    );
  }

  getControls(folder: FormGroup): FormGroup[] {
    return (folder.get('subFolders') as FormArray).controls as FormGroup[];
  }

  removeSubFolder(folder: FormGroup, index: number): void {
    (folder.get('subFolders') as FormArray).removeAt(index);
  }

  removeFolder(folder: { value: { subFolders: string | any[] } }): void {
    this.remove.emit(folder);
  }

  disableAdd(folder: { invalid: any }): void {
    return this.folder.invalid || folder.invalid;
  }
  onKeyup(event: KeyboardEvent): void {
    this.tempName = (event.target as HTMLInputElement).value;
  }
  updateName(folder: FormGroup, name: string): void {
    folder.get('name')?.setValue(name);
    if (this.isInvalid(folder)) {
      folder.get('name')?.updateValueAndValidity();
      return;
    }
  }

  isInvalid(folder: FormGroup): boolean {
    return !folder.get('name')?.valid;
  }
}
<div *ngIf="folder" #folderRow class="folder-row">
  <div class="folder-header">
    <div class="folder-name-container">
      <label for="folderName" class="folder-name-label">Name:</label>
      <input #folderName id="folderName" [ngClass]="isInvalid(folder) ? 'invalid-input' : ''" class="folder-name-input" placeholder="Folder Name" type="text" (keyup)="onKeyup($event)" maxlength="50" (keyup.enter)="updateName(folder, $any($event.target).value)" [value]="folder.value.name" autocomplete="off" />
    </div>
    <button type="button" class="btn-remove-folder" (click)="removeFolder(folder)">Remove</button>
    <button type="button" class="btn-add-subfolder" [disabled]="disableAdd(folder)" (click)="addSubFolder(folder)">Add Subfolder</button>
  </div>
  <div *ngIf="folder && folder.value.subFolders.length > 0" class="subfolder-container">
    <div *ngFor="let subFolder of getControls(folder); let i = index" class="subfolder-item">
      <folder-hierarchy (remove)="removeSubFolder(folder, i)" [folder]="subFolder"></folder-hierarchy>
    </div>
  </div>
</div>
javascript angular recursion angular-reactive-forms angular-forms
1个回答
0
投票

由于文件夹组件中已有

onKeyup
监听器,因此可以获取父表单,并检查是否存在同名元素,例如:

  onKeyup(event: KeyboardEvent): void {

    this.tempName = (event.target as HTMLInputElement).value;
    
    const hasDuplicateName = this.folder.parent.value.filter((el:any, i:number)=> el.name.toLowerCase() === this.tempName.toLowerCase() && i !== this.index);

    if(hasDuplicateName.length > 0) {
      console.log('hasDuplicateName', hasDuplicateName);
      this.folder.setErrors({'duplicateName': true});
    }
  }
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.