我正在动态地使用 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;
}
错误