如何在 Angular 15 中从 @Input() 传递 FormControl

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

我正在动态地使用 Angular Material Chips,并希望将 FormConrol 从任务创建组件传递到 Chips 组件,但是我无法在第一次单击提交按钮时从 Form Group 获取 FormControl 值,当我再次单击它时它会显示 chips 数组值但是当再次更改它显示我 null

芯片组件:

HTML

<mat-form-field [formGroup]="formGroup" class="example-chip-list" appearance="fill">
  <label [for]="controlName" class="control-label">{{label}}</label>
  <mat-chip-grid [formGroup]="formGroup" [formControlName]="controlName" #chipGrid aria-label="Tag selection">
    <mat-chip-row *ngFor="let tag of selectedTags" (removed)="remove(tag)">
      {{tag}}
      <button matChipRemove [attr.aria-label]="'remove ' + tag">
        <mat-icon>cancel</mat-icon>
      </button>
    </mat-chip-row>
  </mat-chip-grid>

  <div class="input-group">
    <img [src]="icon" class="form-control-feedback">
    <input [placeholder]="placeholder" #tagsInputs
           [formGroup]="formGroup"
           [formControlName]="controlName"
           [matChipInputFor]="chipGrid" [matAutocomplete]="auto"
           [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
           (matChipInputTokenEnd)="add($event)" [required]="isRequired">
  </div>
  <span *ngIf="errorMessage != null">
    {{errorMessage}}
  </span>
  <mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">
    <mat-option *ngFor="let tags of filteredTagsChange | async" [value]="tags">
      {{tags}}
    </mat-option>
  </mat-autocomplete>
</mat-form-field> 

打字稿

import {COMMA, ENTER} from '@angular/cdk/keycodes';
import {
  Component,
  ElementRef,
  ViewChild,
  OnInit,
  Input,
  Output,
  EventEmitter,
  SkipSelf,
  Host,
  Optional, Injector, AfterViewInit
} from '@angular/core';
import {MatAutocompleteSelectedEvent} from '@angular/material/autocomplete';
import {MatChipInputEvent} from '@angular/material/chips';
import {Observable} from 'rxjs';
import {map, startWith} from 'rxjs/operators';
import {AbstractControl, ControlContainer, FormControl, FormGroup, NgControl} from "@angular/forms";
import {ChipsService} from "../../../services/chips.service";

@Component({
  selector: 'app-custom-chips-feild',
  templateUrl: './custom-chips-filed.component.html',
  styleUrls: ['./custom-chips-filed.component.scss']
})
export class CustomChipsFiledComponent implements OnInit,AfterViewInit {
  separatorKeysCodes: number[] = [ENTER, COMMA];
  @Input() class!: string;
  @Input() label!: string;
  @Input() type!: string;
  @Input() placeholder!: string;
  @Input() icon!: string;
  @Input() controlName!: string;
  @Input() formGroup!: FormGroup;
  @Input() isRequired!: boolean;
  @Input() errorMessage!: string;
  @Input() selectedTags!:string[];
  @Input() allTags!:string[];
  @Input() filteredTagsChange!: Observable<string[]>;
  @ViewChild('tagsInputs') tagsInputs!: ElementRef<HTMLInputElement>;

  get chipsController():FormControl{
    if (this.formGroup) {
      console.log('formGroup is defined');
      return this.formGroup.get('skills') as FormControl;
    } else {
      console.log('formGroup is undefined');
      return new FormControl();
    }
  }
  constructor() {
    if(this.chipsController){
      console.log('constructor is defined');
    }
    this.filteredTagsChange = this.chipsController.valueChanges.pipe(
      startWith(null),
      map((tags: string | null) => (tags ? this._filter(tags) : this.allTags.slice())),
    );
  } 


} 

  add(event: MatChipInputEvent): void {
    const value = (event.value || '').trim();

    // Check if value is in autocomplete list
    if (this.allTags.includes(value)) {
      // Add the fruit to the chips list
      if (value && !this.selectedTags.includes(value)) {
        this.selectedTags.push(value);
      }

      // Remove the fruit from the autocomplete list
      this.allTags = this.allTags.filter(fruit => fruit !== value);
    }

    // Clear the input value
    event.chipInput!.clear();

    this.chipsController.setValue(null);
  }

  selected(event: MatAutocompleteSelectedEvent): void {
    const value = event.option.value;

    // Add the fruit to the chips list
    if (value && !this.selectedTags.includes(value)) {
      this.selectedTags.push(value);
    }

    // Remove the fruit from the autocomplete list
    this.allTags = this.allTags.filter(fruit => fruit !== value);

    // Clear the input value
    this.tagsInputs.nativeElement.value = '';
    this.chipsController.setValue(null);
  }

  remove(tag: string): void {
    const index = this.selectedTags.indexOf(tag);

    if (index >= 0) {
      this.selectedTags.splice(index, 1);
    }
  }

  private _filter(value: string): string[] {
    const filterValue = value.toLowerCase();
    return this.allTags.filter(fruit => fruit.toLowerCase().includes(filterValue));
  } 

任务组成:

HTML

<div class="task_creation_form">
  <form [formGroup]="formGroup" (ngSubmit)="submit()">
    <app-custom-textarea placeholder="Enter your Description" [controlName]="'description'" [formGroup]="formGroup" label="Task Description" [rows]="3" icon="assets/Icons/details.svg"></app-custom-textarea>
    <div class="task_assigning_group">
      <app-custom-dropdown [dropdownOptions]="rolesItem" label="Role" placeholder="Enter your Role" icon="assets/Icons/role.svg" subIcon="assets/Icons/dropdown.svg"
                           [controlName]="'type'" [formGroup]="formGroup" required="true"/>
      <app-custom-dropdown [dropdownOptions]="rolesItem" label="Role" placeholder="Enter your Role" icon="assets/Icons/role.svg" subIcon="assets/Icons/dropdown.svg"
                           [controlName]="'priority'" [formGroup]="formGroup" required="true"/>
    </div>
    <app-custom-chips-feild
      label="Skills"
      placeholder="Enter your Skills"
      icon="assets/Icons/skills.svg"
      [formGroup]="formGroup"
      [controlName]="'skills'"
      [allTags]="allTags"
      [selectedTags]="selectedTags"
      required="true"></app-custom-chips-feild>
    <app-custom-submit-button [isSubmit]="true" [btnName]="'Register'" class="auth-form-submit" [formGroup]="formGroup" />
  </form>
</div>
 

打字稿

import {Component, ElementRef, ViewChild} from '@angular/core';
import {AuthService} from "../../../../services/auth.service";
import {RegistrationEmailService} from "../../../../services/registration-email.service";
import {FormControl, FormGroup, Validators} from "@angular/forms";
import {ChipsService} from "../../../../services/chips.service";
import {Observable} from "rxjs";
import {map, startWith} from "rxjs/operators";
import {MatChipInputEvent} from "@angular/material/chips";
import {MatAutocompleteSelectedEvent} from "@angular/material/autocomplete";
import {COMMA, ENTER} from "@angular/cdk/keycodes";

@Component({
  selector: 'app-task-creation',
  templateUrl: './task-creation.component.html',
  styleUrls: ['./task-creation.component.scss']
})
export class TaskCreationComponent {
  @ViewChild('tagsInput') tagsInput!: ElementRef<HTMLInputElement>;
  separatorKeysCodes: number[] = [ENTER, COMMA];
  filteredTags: Observable<string[]>;
  selectedTags: string[] = [];
  allTags: string[] = ['Apple', 'Lemon', 'Lime', 'Orange', 'Strawberry'];

  rolesItem = [
    {id: 1, name: 'Admin'},
    {id: 2, name: 'User'},
  ];
  formGroup: FormGroup = new FormGroup({
    description: new FormControl('', [
      Validators.required,
    ]),
    type : new FormControl('', [
      Validators.required,
    ]),
    priority : new FormControl('', [
      Validators.required,
    ]),
    skills: new FormControl('',[]),
  })
  chipsController!:FormControl;

  constructor(private authService:AuthService,private emailService:RegistrationEmailService){
    this.chipsController = this.formGroup.get('skills') as FormControl;
    if(this.chipsController){
      console.log('formGroup is defined');
    }
  }

  submit() {
    console.log(this.formGroup.value);
  }

  protected readonly FormControl = FormControl;
}

 

错误

enter image description here

angular angularjs typescript angular-material angular-reactive-forms
© www.soinside.com 2019 - 2024. All rights reserved.