复选框被选中,但它们在页面重新加载时没有初始值
Checkboxes are checked but they have no initial value on page reload
当我 check/uncheck 个框并提交到服务器时,当前设置工作正常。
然而,当页面重新加载或当我去编辑时,页面加载正常并且复选框正在检查正确的条目,就像这样...
这里的问题是当我点击提交而不触及任何值时,提交的数组是空的 permission_ids: []
,需要再次点击它们才能触发 OnChange()
而我不能当我加载页面时自动执行此操作,因为我是 Angular
的新手
据我了解,这里的问题是选中了复选框,但未更新表单的值。
这是代码
模板
<h4>Permissions</h4>
<div class="form-group row p-t-20">
<div class="col-sm-4">
<div class="custom-control custom-checkbox" *ngFor="let perm of permissions; let i=index">
<input
type="checkbox"
class="custom-control-input"
id="permission_{{perm.id}}"
[value]="perm.id"
(change)="onPermissionCheckboxChange($event)"
[checked]="permissionExists(perm.id)">
<label
class="custom-control-label"
for="permission_{{perm.id}}">
{{ perm.name }}
</label>
</div>
</div>
</div>
TS
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, FormControl, Validators } from "@angular/forms";
import { NotificationService } from "../../notification/notification.service";
import { PermissionsService } from "../../permissions/permissions.service";
import { HttpClient } from "@angular/common/http";
import { environment } from "../../../../environments/environment";
import { Router, ActivatedRoute } from "@angular/router";
import { RolesService } from "../roles.service";
@Component({
selector: 'app-edit-role',
templateUrl: './edit-role.component.html',
styleUrls: ['./edit-role.component.css']
})
export class EditRoleComponent implements OnInit {
isLoading: boolean = false;
roleId: number = +this.route.snapshot.params['id']
roleObj: any = {};
haveRole: any = true;
roles: any;
role: any;
permissions: any;
form: FormGroup;
constructor(
private http: HttpClient,
private router: Router,
private route: ActivatedRoute,
private fb: FormBuilder,
private notificationService: NotificationService,
private rolesService: RolesService,
private permissionsService: PermissionsService
) {
this.form = this.fb.group({
role: new FormGroup({
name: new FormControl('', [Validators.required]),
permission_ids: this.fb.array([])
})
})
}
permissionExists(id: number) {
return this.role.permissions.find(function(el: any){ return el.id === id }) !== undefined;
}
ngOnInit(): void {
this.rolesService.getRoles().subscribe(response => {
this.roles = response.body;
this.role = this.roles.find((el: any) => el.id === this.roleId)
//console.log(this.role);
this.isLoading = false;
this.form.patchValue({
'role': {
'name': this.role.name
}
});
},
error => {
this.isLoading = false;
this.notificationService.showNotification(
error.error.title,
error.error.details,
'error'
);
})
this.permissionsService.getPermissions().subscribe(response => {
this.permissions = response.body;
this.isLoading = false;
},
error => {
this.isLoading = false;
// console.log(error.error);
this.notificationService.showNotification(
error.error.title,
error.error.details,
'error'
);
})
}
onPermissionCheckboxChange(e: any) {
const checkArray: FormArray = this.form.get('role.permission_ids') as FormArray;
if (e.target.checked) {
checkArray.push(new FormControl(e.target.value));
} else {
let i: number = 0;
checkArray.controls.forEach((item: any) => {
if (item.value == e.target.value) {
checkArray.removeAt(i);
return;
}
i++;
});
}
}
onSubmit() {
this.roleObj.role = this.form.value.role
console.log(this.roleObj)
}
}
请原谅我糟糕的代码,但我仍在学习 angular 因为我主要 Ruby 在 Rails 开发人员
阿米尔,你的代码有点混乱。 (此外,您还混合了 FormBuilder 和 FormControl 的构造函数)
先想对象,后创建表单。我想你的“角色”就像,例如
{
name:'name',
permissions:[1,3]
}
还有你的权限和数组
[{id:1,name:"Can create category"},{id:2,name:"Can read category}...]
Angular 中的输入类型“checkbox”只有两个值:true 或 false,因此如果您使用 FormArray,其值将是例如[true,false,true,false,false]
所以一种方法可以创建一个 FormGroup,例如
form = new FormGroup({
name: new FormControl(this.role.name, [Validators.required]),
permissions: new FormArray(
this.permissions.map(
x => new FormControl(this.role.permissions.find(p => p == x.id) != null)
)
)
});
要管理,请创建一个 getter rolePermision,return formArray
get rolePermision()
{
return this.form.get('permissions') as FormArray
}
还有一个html喜欢
<form [formGroup]="form">
<input formControlName="name">
<div formArrayName="permissions">
<div *ngFor="let control of rolePermision.controls;let i=index">
<input
[formControlName]="i" type="checkbox">{{permissions[i].name}}
</div>
</div>
</form>
然后,提交后
submit(form: FormGroup) {
if (form.valid) {
const data = {
name: this.form.value.name,
permisions: this.permissions
.filter((x, index) => form.value.permissions[index])
.map(x => x.id)
};
...use data to send to your service..
}
}
另一种方法是让一个 formGroup 有两个 formControl,其中一个存储一个数组
form = new FormGroup({
name: new FormControl(this.role.name, [Validators.required]),
permissions:new FormControl(this.role.permissions)
})
并使用 [ngModel] 和 (ngModelChange)
<form [formGroup]="form">
<input formControlName="name">
<div *ngFor="let permision of permissions">
<input type="checkbox" [ngModel]="form.get('permissions')?.value && form.get('permissions').value.indexOf(permision.id)>=0"
[ngModelOptions]="{standalone:true}"
(ngModelChange)="change(permision.id,$event)"
>{{permision.name}}
</div>
</form>
功能变化如
change(id: any, checked: boolean) {
const oldValue = this.form.value.permissions;
const permissions = checked
? this.permissions.filter(
x => (oldValue && oldValue.indexOf(x.id) >= 0) || x.id == id
)
: this.permissions.filter(
x => oldValue && oldValue.indexOf(x.id) >= 0 && x.id != id
);
this.form
.get('permissions')
.setValue(permissions.length > 0 ? permissions.map(x => x.id) : null);
}
您可以在this stackblitz
中获得两种方法
当我 check/uncheck 个框并提交到服务器时,当前设置工作正常。
然而,当页面重新加载或当我去编辑时,页面加载正常并且复选框正在检查正确的条目,就像这样...
这里的问题是当我点击提交而不触及任何值时,提交的数组是空的 permission_ids: []
,需要再次点击它们才能触发 OnChange()
而我不能当我加载页面时自动执行此操作,因为我是 Angular
据我了解,这里的问题是选中了复选框,但未更新表单的值。
这是代码
模板
<h4>Permissions</h4>
<div class="form-group row p-t-20">
<div class="col-sm-4">
<div class="custom-control custom-checkbox" *ngFor="let perm of permissions; let i=index">
<input
type="checkbox"
class="custom-control-input"
id="permission_{{perm.id}}"
[value]="perm.id"
(change)="onPermissionCheckboxChange($event)"
[checked]="permissionExists(perm.id)">
<label
class="custom-control-label"
for="permission_{{perm.id}}">
{{ perm.name }}
</label>
</div>
</div>
</div>
TS
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, FormControl, Validators } from "@angular/forms";
import { NotificationService } from "../../notification/notification.service";
import { PermissionsService } from "../../permissions/permissions.service";
import { HttpClient } from "@angular/common/http";
import { environment } from "../../../../environments/environment";
import { Router, ActivatedRoute } from "@angular/router";
import { RolesService } from "../roles.service";
@Component({
selector: 'app-edit-role',
templateUrl: './edit-role.component.html',
styleUrls: ['./edit-role.component.css']
})
export class EditRoleComponent implements OnInit {
isLoading: boolean = false;
roleId: number = +this.route.snapshot.params['id']
roleObj: any = {};
haveRole: any = true;
roles: any;
role: any;
permissions: any;
form: FormGroup;
constructor(
private http: HttpClient,
private router: Router,
private route: ActivatedRoute,
private fb: FormBuilder,
private notificationService: NotificationService,
private rolesService: RolesService,
private permissionsService: PermissionsService
) {
this.form = this.fb.group({
role: new FormGroup({
name: new FormControl('', [Validators.required]),
permission_ids: this.fb.array([])
})
})
}
permissionExists(id: number) {
return this.role.permissions.find(function(el: any){ return el.id === id }) !== undefined;
}
ngOnInit(): void {
this.rolesService.getRoles().subscribe(response => {
this.roles = response.body;
this.role = this.roles.find((el: any) => el.id === this.roleId)
//console.log(this.role);
this.isLoading = false;
this.form.patchValue({
'role': {
'name': this.role.name
}
});
},
error => {
this.isLoading = false;
this.notificationService.showNotification(
error.error.title,
error.error.details,
'error'
);
})
this.permissionsService.getPermissions().subscribe(response => {
this.permissions = response.body;
this.isLoading = false;
},
error => {
this.isLoading = false;
// console.log(error.error);
this.notificationService.showNotification(
error.error.title,
error.error.details,
'error'
);
})
}
onPermissionCheckboxChange(e: any) {
const checkArray: FormArray = this.form.get('role.permission_ids') as FormArray;
if (e.target.checked) {
checkArray.push(new FormControl(e.target.value));
} else {
let i: number = 0;
checkArray.controls.forEach((item: any) => {
if (item.value == e.target.value) {
checkArray.removeAt(i);
return;
}
i++;
});
}
}
onSubmit() {
this.roleObj.role = this.form.value.role
console.log(this.roleObj)
}
}
请原谅我糟糕的代码,但我仍在学习 angular 因为我主要 Ruby 在 Rails 开发人员
阿米尔,你的代码有点混乱。 (此外,您还混合了 FormBuilder 和 FormControl 的构造函数)
先想对象,后创建表单。我想你的“角色”就像,例如
{
name:'name',
permissions:[1,3]
}
还有你的权限和数组
[{id:1,name:"Can create category"},{id:2,name:"Can read category}...]
Angular 中的输入类型“checkbox”只有两个值:true 或 false,因此如果您使用 FormArray,其值将是例如[true,false,true,false,false]
所以一种方法可以创建一个 FormGroup,例如
form = new FormGroup({
name: new FormControl(this.role.name, [Validators.required]),
permissions: new FormArray(
this.permissions.map(
x => new FormControl(this.role.permissions.find(p => p == x.id) != null)
)
)
});
要管理,请创建一个 getter rolePermision,return formArray
get rolePermision()
{
return this.form.get('permissions') as FormArray
}
还有一个html喜欢
<form [formGroup]="form">
<input formControlName="name">
<div formArrayName="permissions">
<div *ngFor="let control of rolePermision.controls;let i=index">
<input
[formControlName]="i" type="checkbox">{{permissions[i].name}}
</div>
</div>
</form>
然后,提交后
submit(form: FormGroup) {
if (form.valid) {
const data = {
name: this.form.value.name,
permisions: this.permissions
.filter((x, index) => form.value.permissions[index])
.map(x => x.id)
};
...use data to send to your service..
}
}
另一种方法是让一个 formGroup 有两个 formControl,其中一个存储一个数组
form = new FormGroup({
name: new FormControl(this.role.name, [Validators.required]),
permissions:new FormControl(this.role.permissions)
})
并使用 [ngModel] 和 (ngModelChange)
<form [formGroup]="form">
<input formControlName="name">
<div *ngFor="let permision of permissions">
<input type="checkbox" [ngModel]="form.get('permissions')?.value && form.get('permissions').value.indexOf(permision.id)>=0"
[ngModelOptions]="{standalone:true}"
(ngModelChange)="change(permision.id,$event)"
>{{permision.name}}
</div>
</form>
功能变化如
change(id: any, checked: boolean) {
const oldValue = this.form.value.permissions;
const permissions = checked
? this.permissions.filter(
x => (oldValue && oldValue.indexOf(x.id) >= 0) || x.id == id
)
: this.permissions.filter(
x => oldValue && oldValue.indexOf(x.id) >= 0 && x.id != id
);
this.form
.get('permissions')
.setValue(permissions.length > 0 ? permissions.map(x => x.id) : null);
}
您可以在this stackblitz
中获得两种方法