angular - 如何使用反应式表单进行动态默认选中的复选框
angular - How to do dynamic default checked checkboxes with reactive forms
我有一个编辑个人资料表格。因为有动态复选框。如果用户更新了复选框一次,那么它应该选中默认值。
这是我的 ts 文件...
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { ApplicantsService } from '@app/services/applicants.service';
@Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
myForm: FormGroup;
submitted = false;
userid: any;
skills: any;
experience: any;
applicant_skills: any;
profile: any;
states: any;
cities: any;
profilePicture: any;
constructor(
private formBuilder: FormBuilder,
private applicantsService: ApplicantsService,
) { }
ngOnInit(): void {
this.userid = JSON.parse(localStorage.getItem('currentUser')).user_id;
this.myForm = this.formBuilder.group({
userid: [''],
first_name: new FormControl({value: null, disabled: true}, Validators.required),
last_name: new FormControl({value: null, disabled: true}, Validators.required),
email: new FormControl({value: null, disabled: true}, Validators.required),
mobile: ['', Validators.required],
state: ['', Validators.required],
city: ['', Validators.required],
skills: this.formBuilder.array([], [Validators.required]),
});
this.applicantsService.getProfile(this.userid).subscribe( res => {
this.profile = res.data[0];
this.myForm.patchValue(this.profile);
})
this.applicantsService.getApplicantskills(this.userid).subscribe( res =>
{
if(res && res.data)
{
this.applicant_skills = res.data;
}
})
}
// convenience getter for easy access to form fields
get f() { return this.myForm.controls; }
onCheckboxChange(e) {
const checkArray: FormArray = this.myForm.get('skills') as FormArray;
if (e.target.checked) {
checkArray.push(new FormControl(e.target.value));
} else {
let i: number = 0;
checkArray.controls.forEach((item: FormControl) => {
if (item.value == e.target.value) {
checkArray.removeAt(i);
return;
}
i++;
});
}
}
onSubmit()
{
this.submitted = true;
// stop here if form is invalid
if (this.myForm.invalid) {
console.log(this.myForm)
return;
}
console.log("this.myForm.value", this.myForm.value);
}
}
这是我的 html 页面。
<!-- Spinner -->
<ngx-spinner></ngx-spinner>
<section id="profile-form" class="bg-grey">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-10 col-md-12">
<h1 class="text-center">Update your profile</h1>
<div class="form p-md-6">
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
<div class="form-row">
<div class="form-group d-none">
<input type="text" formControlName="userid" value={{userid}}>
</div>
<div class="form-group col-md-6">
<label for="linkedin">First Name</label>
<input type="text" class="form-control" formControlName="first_name" placeholder="First Name">
</div>
<div class="form-group col-md-6">
<label for="lastname">Last Name</label>
<input type="text" class="form-control" formControlName="last_name" placeholder="Last Name">
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="linkedin">Email ID</label>
<input type="email" class="form-control" formControlName="email" placeholder="Email ID">
</div>
<div class="form-group col-md-6">
<label for="lastname">Cellphone Number</label>
<input type="text" class="form-control" formControlName="mobile" placeholder="Cellphone Number" [ngClass]="{ 'is-invalid': submitted && f.mobile.errors }" required>
<div *ngIf="submitted && f.mobile.errors" class="invalid-feedback">
<div *ngIf="f.mobile.errors.required">This field is required</div>
</div>
</div>
</div>
<div class="form-row">
<div class="button-group-pills text-center col-md-12" data-toggle="buttons">
<label class="btn btn-default" *ngFor="let skill of skills">
<input type="checkbox" formArrayName="skills" (change)="onCheckboxChange($event)" value={{skill.id}} [ngClass]="{ 'is-invalid': submitted && f.skills.errors }" required>
<div>{{skill.skill}}</div>
</label>
<div *ngIf="submitted && f.skills.errors" class="error">
<div *ngIf="f.skills.errors.required">This field is required</div>
</div>
</div>
</div>
<div class="form-row justify-content-center text-center pt-4 pb-2">
<div class="col-md-8">
<button type="submit" class="btn btn-apply px-4">save profile</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</section>
请帮忙...................................... ..................................................... ..................................................... ..................................................... ..................................................... .........
您通过检查当前值是否在 checkArray
数组
中来切换 [checked]
值
将其包含在您的输入字段中
[checked]="checkArray.includes(skill.id)"
所以你的输入变成
<input type="checkbox" formArrayName="skills" (change)="onCheckboxChange($event)" [checked]="checkArray.includes(skill.id)
value={{skill.id}} [ngClass]="{ 'is-invalid': submitted && f.skills.errors }" required>
更新
如果您仅将技能的 id
推入数组,则上述方法会起作用。但是由于您要推送整个 skill
对象,您可以改为检查该对象。
[checked]="checkArray.includes(skill)"
<input type="checkbox" formArrayName="skills" (change)="onCheckboxChange($event)" [checked]="checkArray.includes(skill)
value={{skill.id}} [ngClass]="{ 'is-invalid': submitted && f.skills.errors }" required>
Sadique,我想你希望你的“技能”是一组值。我没有找到我在 ReactiveForms 中使用 ngModel 来管理复选框列表的 SO。最接近的是
想法是您没有 FormArray,只有 FormControl,并且您使用 [(ngModel)] 为 formControl 赋值。是的,一个 FormControl 可以存储一个数组,是的,即使你没有在 .html
中输入,也存在一个 FormControl
<label class="btn btn-default" *ngFor="let skill of skills">
<input type="checkbox"
[ngModelOptions]="{standalone:true}"
<!--see that "is checked" if in the array you has the value-->
[ngModel]="(myForm.get('skills').value || []).indexOf(skill.id)>=0"
<!--when change, we call to the function-->
(ngModelChange)="onChange($event,skill.id)" >
<div>{{skill.skill}}</div>
</label>
和
onChange(checked: boolean, id: number) {
const control = this.myForm.get("skills"); //get the control
let value = control.value || []; //get the value, if null an empty array
if (checked && value.indexOf(id) < 0) //if we checked and it's not in the array
value = [...value, id].sort((a, b) => //concatenate the value and sort
this.skills.findIndex(f => f.id == a) >
this.skills.findIndex(f => f.id == b)? 1: -1
);
if (!checked) value = value.filter(x => x != id); //if not checked remove it
control.setValue(value.length ? value : null); //finally set value
//see that is nothing selected, give value null
//this make that we can use Validators.required
}
我有一个编辑个人资料表格。因为有动态复选框。如果用户更新了复选框一次,那么它应该选中默认值。
这是我的 ts 文件...
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { ApplicantsService } from '@app/services/applicants.service';
@Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
myForm: FormGroup;
submitted = false;
userid: any;
skills: any;
experience: any;
applicant_skills: any;
profile: any;
states: any;
cities: any;
profilePicture: any;
constructor(
private formBuilder: FormBuilder,
private applicantsService: ApplicantsService,
) { }
ngOnInit(): void {
this.userid = JSON.parse(localStorage.getItem('currentUser')).user_id;
this.myForm = this.formBuilder.group({
userid: [''],
first_name: new FormControl({value: null, disabled: true}, Validators.required),
last_name: new FormControl({value: null, disabled: true}, Validators.required),
email: new FormControl({value: null, disabled: true}, Validators.required),
mobile: ['', Validators.required],
state: ['', Validators.required],
city: ['', Validators.required],
skills: this.formBuilder.array([], [Validators.required]),
});
this.applicantsService.getProfile(this.userid).subscribe( res => {
this.profile = res.data[0];
this.myForm.patchValue(this.profile);
})
this.applicantsService.getApplicantskills(this.userid).subscribe( res =>
{
if(res && res.data)
{
this.applicant_skills = res.data;
}
})
}
// convenience getter for easy access to form fields
get f() { return this.myForm.controls; }
onCheckboxChange(e) {
const checkArray: FormArray = this.myForm.get('skills') as FormArray;
if (e.target.checked) {
checkArray.push(new FormControl(e.target.value));
} else {
let i: number = 0;
checkArray.controls.forEach((item: FormControl) => {
if (item.value == e.target.value) {
checkArray.removeAt(i);
return;
}
i++;
});
}
}
onSubmit()
{
this.submitted = true;
// stop here if form is invalid
if (this.myForm.invalid) {
console.log(this.myForm)
return;
}
console.log("this.myForm.value", this.myForm.value);
}
}
这是我的 html 页面。
<!-- Spinner -->
<ngx-spinner></ngx-spinner>
<section id="profile-form" class="bg-grey">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-10 col-md-12">
<h1 class="text-center">Update your profile</h1>
<div class="form p-md-6">
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
<div class="form-row">
<div class="form-group d-none">
<input type="text" formControlName="userid" value={{userid}}>
</div>
<div class="form-group col-md-6">
<label for="linkedin">First Name</label>
<input type="text" class="form-control" formControlName="first_name" placeholder="First Name">
</div>
<div class="form-group col-md-6">
<label for="lastname">Last Name</label>
<input type="text" class="form-control" formControlName="last_name" placeholder="Last Name">
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="linkedin">Email ID</label>
<input type="email" class="form-control" formControlName="email" placeholder="Email ID">
</div>
<div class="form-group col-md-6">
<label for="lastname">Cellphone Number</label>
<input type="text" class="form-control" formControlName="mobile" placeholder="Cellphone Number" [ngClass]="{ 'is-invalid': submitted && f.mobile.errors }" required>
<div *ngIf="submitted && f.mobile.errors" class="invalid-feedback">
<div *ngIf="f.mobile.errors.required">This field is required</div>
</div>
</div>
</div>
<div class="form-row">
<div class="button-group-pills text-center col-md-12" data-toggle="buttons">
<label class="btn btn-default" *ngFor="let skill of skills">
<input type="checkbox" formArrayName="skills" (change)="onCheckboxChange($event)" value={{skill.id}} [ngClass]="{ 'is-invalid': submitted && f.skills.errors }" required>
<div>{{skill.skill}}</div>
</label>
<div *ngIf="submitted && f.skills.errors" class="error">
<div *ngIf="f.skills.errors.required">This field is required</div>
</div>
</div>
</div>
<div class="form-row justify-content-center text-center pt-4 pb-2">
<div class="col-md-8">
<button type="submit" class="btn btn-apply px-4">save profile</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</section>
请帮忙...................................... ..................................................... ..................................................... ..................................................... ..................................................... .........
您通过检查当前值是否在 checkArray
数组
[checked]
值
将其包含在您的输入字段中
[checked]="checkArray.includes(skill.id)"
所以你的输入变成
<input type="checkbox" formArrayName="skills" (change)="onCheckboxChange($event)" [checked]="checkArray.includes(skill.id)
value={{skill.id}} [ngClass]="{ 'is-invalid': submitted && f.skills.errors }" required>
更新
如果您仅将技能的 id
推入数组,则上述方法会起作用。但是由于您要推送整个 skill
对象,您可以改为检查该对象。
[checked]="checkArray.includes(skill)"
<input type="checkbox" formArrayName="skills" (change)="onCheckboxChange($event)" [checked]="checkArray.includes(skill)
value={{skill.id}} [ngClass]="{ 'is-invalid': submitted && f.skills.errors }" required>
Sadique,我想你希望你的“技能”是一组值。我没有找到我在 ReactiveForms 中使用 ngModel 来管理复选框列表的 SO。最接近的是
想法是您没有 FormArray,只有 FormControl,并且您使用 [(ngModel)] 为 formControl 赋值。是的,一个 FormControl 可以存储一个数组,是的,即使你没有在 .html
中输入,也存在一个 FormControl <label class="btn btn-default" *ngFor="let skill of skills">
<input type="checkbox"
[ngModelOptions]="{standalone:true}"
<!--see that "is checked" if in the array you has the value-->
[ngModel]="(myForm.get('skills').value || []).indexOf(skill.id)>=0"
<!--when change, we call to the function-->
(ngModelChange)="onChange($event,skill.id)" >
<div>{{skill.skill}}</div>
</label>
和
onChange(checked: boolean, id: number) {
const control = this.myForm.get("skills"); //get the control
let value = control.value || []; //get the value, if null an empty array
if (checked && value.indexOf(id) < 0) //if we checked and it's not in the array
value = [...value, id].sort((a, b) => //concatenate the value and sort
this.skills.findIndex(f => f.id == a) >
this.skills.findIndex(f => f.id == b)? 1: -1
);
if (!checked) value = value.filter(x => x != id); //if not checked remove it
control.setValue(value.length ? value : null); //finally set value
//see that is nothing selected, give value null
//this make that we can use Validators.required
}