简体   繁体   English

如何异步检查用户名是否已使用 formControl?

[英]How to asynchronously check if a username is already taken with formControl?

This is my method where i try to check from the database which usernames are already taken:这是我尝试从数据库中检查已使用哪些用户名的方法:

takenUsernames(control: FormControl): Promise<any> | Observable<any> {
    const promise = new Promise<any>((resolve, reject) => {
      this.employeeService.getEmployeeList().subscribe((employees) => {
        this.employees = employees;
        for (let employee of control.value) {
          if (this.employees.indexOf(employee) !== -1) {
            resolve({ usernameIsTaken: true });
          } else {
            resolve(null);
          }
        }
      });
    });
    return promise;
  }

And this is my formGroup object:这是我的表单组 object:

this.newProjectForm = new FormGroup({
      projectName: new FormControl(null, Validators.required),
      description: new FormControl(null),
      assignedEmployees: new FormControl(null, [Validators.required]),
      employees: new FormArray(
        [],
        [this.forbidUsernames.bind(this)],
        [this.takenUsernames.bind(this)]
      ),
    });

As you can see employees is a FormArray so i loop true control.value to check each username but it doesnt seem to work.正如您所看到的,员工是一个 FormArray,所以我循环真正的 control.value 来检查每个用户名,但它似乎不起作用。 The problem is in the takenUsernames function because i dont get the pending status if i inspect the element.问题出在 takeUsernames function 中,因为如果我检查该元素,我不会得到挂起状态。

Here's the whole html code:这是整个 html 代码:

link
  href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@600&family=Roboto+Mono:wght@500&display=swap"
  type="text"
  rel="stylesheet"
/>

<div class="backdrop" (click)="onFormAlertClose()"></div>
<div class="alert-box">
  <form [formGroup]="newProjectForm" (ngSubmit)="onSubmit()">
    <h3>New Project Form</h3>
    <div class="form-group">
      <label for="projectName">Project Name</label>
      <input
        type="text"
        id="projectName"
        class="form-control"
        [formControlName]="'projectName'"
      />
      <!-- if omit [] also omit ''-->
      <span
        *ngIf="
          !newProjectForm.get('projectName').valid &&
          newProjectForm.get('projectName').touched
        "
        >Please enter a project name</span
      >
    </div>
    <div class="form-group">
      <label for="description">Description</label>
      <textarea
        id="description"
        class="form-control"
        formControlName="description"
      ></textarea>
    </div>
    <div class="form-group">
      <label for="assignedEmployees">Assign Employees</label>
      <div class="larger-width-divider"></div>
      <input type="text" class="search-box" placeholder="Search..." />
      <select
        name="employees"
        class="form-control"
        multiple
        size="employees.length"
        formControlName="assignedEmployees"
      >
        <ng-container *ngIf="newProjectForm.get('projectName').valid">
          <option id="option" *ngFor="let employee of employees">{{
            employee.userName
          }}</option>
        </ng-container>
      </select>
      <span
        *ngIf="
          !newProjectForm.get('assignedEmployees').valid &&
          newProjectForm.get('assignedEmployees').touched
        "
        >Please select at least one employee</span
      >
    </div>
    <div>
      <button
        type="button"
        class="add-emp-btn"
        *ngIf="!addEmployeeBtnClicked"
        (click)="onEmpBtnClicked()"
        [disabled]="newProjectForm.invalid"
      >
        Add Employees
      </button>
      <ng-container *ngIf="addEmployeeBtnClicked" formArrayName="employees">
        <div *ngFor="let employeesControl of getControls(); let i = index">
          <label for="userName">Insert one or multiple employee</label>
          <input type="text" [formControlName]="i" />
          <div class="width-divider"></div>
          <button
            type="button"
            class="goto-add-emp-btn"
            (click)="onEmpBtnClicked()"
          >
            Cancel
          </button>
          <div>
            <span
              class="last-span"
              *ngIf="
                !newProjectForm.get('employees').valid &&
                newProjectForm.get('employees').touched
              "
            >
              <span
                *ngIf="newProjectForm.get('employees').errors?.nameIsForbidden"
                >This name is invalid!</span
              >
              <span *ngIf="newProjectForm.get('employees').errors?.required"
                >Add at least on employee</span
              >
              <span
                *ngIf="newProjectForm.get('employees').errors?.usernameIsTaken"
              ></span>
            </span>
          </div>
        </div>
      </ng-container>
    </div>
    <div class="height-divider"></div>
    <div class="alert-box-actions">
      <button type="submit" class="submit" [disabled]="!newProjectForm.valid">
        Create
      </button>
      <div class="width-divider"></div>
      <button type="button" (click)="onFormAlertClose()">Cancel</button>
    </div>
  </form>
</div>

And here's the whole class:这是整个 class:

import { Component, Output, OnInit } from "@angular/core";
import { Subject, Observable } from "rxjs";
import { ProjectService } from "src/app/services/project.service";
import { FormGroup, FormControl, Validators, FormArray } from "@angular/forms";
import { IEmployee } from "../entities/employee";
import { EmployeeService } from "src/app/services/employee.service";

@Component({
  selector: "app-alert",
  templateUrl: "./new-project-form-alert.component.html",
  styleUrls: ["./new-project-form-alert.component.css"],
})
export class AlertComponent implements OnInit {
  closeNewProjectAlert: Subject<boolean> = new Subject<boolean>();
  employees: IEmployee[];
  newProjectForm: FormGroup;
  addEmployeeBtnClicked = false;
  forbiddenUsernames = [
    "Admin",
    "Manager",
    "Developer",
    "Guest",
    "admin",
    "manager",
    "developer",
    "guest",
  ];

  constructor(
    private projectService: ProjectService,
    private employeeService: EmployeeService
  ) {}

  ngOnInit() {
    this.employeeService.getEmployeeList().subscribe((employees) => {
      this.employees = employees;
    });
    this.newProjectForm = new FormGroup({
      // properties are string so when the files is minified they are not destroyed
      projectName: new FormControl(null, Validators.required),
      description: new FormControl(null),
      assignedEmployees: new FormControl(null, [Validators.required]),
      employees: new FormArray(
        [],
        [this.forbidUsernames.bind(this)],
        this.takenUsernames
      ),
    });
  }

  onFormAlertClose() {
    this.projectService.closeNewProjectForm$.next(true);
  }

  onSubmit() {
    console.log(this.newProjectForm);
    this.newProjectForm.reset();
    this.onFormAlertClose();
    console.log((<FormArray>this.newProjectForm.get("employees")).controls);
  }

  onEmpBtnClicked() {
    if (!this.addEmployeeBtnClicked) {
      this.addEmployeeBtnClicked = true;
      const control = new FormControl(null, Validators.required);
      (<FormArray>this.newProjectForm.get("employees")).push(control);
    } else {
      this.addEmployeeBtnClicked = false;
      (<FormArray>this.newProjectForm.get("employees")).removeAt(0);
    }
  }

  forbidUsernames(control: FormControl): { [s: string]: boolean } {
    for (let employee of control.value) {
      if (this.forbiddenUsernames.indexOf(employee) !== -1) {
        return { nameIsForbidden: true };
      }
    }
    return null; // this if username is valid, do not return false
  }

  takenUsernames(control: FormControl): Promise<any> | Observable<any> {
    const promise = new Promise<any>((resolve, reject) => {
      const observable = this.employeeService.getEmployeeList().subscribe((employees) => {
        this.employees = employees;
        for (let employee of control.value) {
          if (this.employees.indexOf(employee) !== -1) {
            resolve({ usernameIsTaken: true });
          } else {
            resolve(null);
          }
        }
      });
    });
    return promise;
  }

  getControls() {
    return (<FormArray>this.newProjectForm.get("employees")).controls;
  }
}

Sorry i know it a big mess, it's my first web app.抱歉,我知道这是一团糟,这是我的第一个 web 应用程序。

Edit: i provided a small video of the form if it helps: https://streamable.com/ua7mcq编辑:如果有帮助,我提供了一个表格的小视频: https://streamable.com/ua7mcq

Well yep, i have named the formArray as employees because when i submit the form the username or usernames get added to IEmployee objects and saved in the database.是的,我已将 formArray 命名为员工,因为当我提交表单时,用户名或用户名被添加到 IEmployee 对象并保存在数据库中。

But of the time of typing the usernames they are just string and i was comparing these strings with the employee objects.但是在输入用户名时,它们只是字符串,我正在将这些字符串与员工对象进行比较。 So here's it fixed:所以这里是固定的:

takenUsernames(control: FormControl): Promise<any> | Observable<any> {
    const promise = new Promise<any>((resolve, reject) => {
      const observable = this.employeeService.getEmployeeList().subscribe((employees) => {
        this.employees = employees;
        const usernames = this.employees.map(employee => employee.userName)
        console.log(usernames)
        for (let employee of control.value) {
          if (usernames.indexOf(employee) !== -1) {
            resolve({ usernameIsTaken: true });
          } else {
            resolve(null);
          }
        }
      });
    });
    return promise;
  }

But now i will reduce the input box to be able to add just one employee at time, wasted too much time on these component.但是现在我将减少输入框,以便一次只能添加一名员工,在这些组件上浪费了太多时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM