angular - 根据从后端返回的数据添加 FormControl 但在 Angular 应用程序中出现两个不同的错误
问题描述
这是我的 Angular 应用程序的页面之一。
在 ngOnInit 方法中,我调用 api 两次以获取我需要的不同数据,并通过使用 forEach 方法循环数据来构建反应式表单,但不知何故,我遇到了两个不同的错误之一。
这个
和这个
有时根本没有错误。
如果有人能告诉我我的代码有什么问题,将不胜感激。
这是我的代码的一部分
用户管理器.component.ts
export class UserManagerComponent implements OnInit {
constructor(
private fb: FormBuilder
) {}
ngOnInit(): void {
this.commonData.getDropdownData('menus')
.pipe(takeWhile(() => this.alive))
.subscribe(r => {
if (r.status === 0) {
this.menuForm = this.fb.group({});
this.menuList = r.result.menus;
this.menuList.forEach(i => {
const control = new FormControl();
(this.menuForm as FormGroup).setControl(i.MenuId, control);
i.children.forEach(a => {
const con = new FormControl();
(this.menuForm as FormGroup).setControl(a.MenuId, con);
});
});
this.isMenuFormReady = true;
} else {
this.toastrService.danger(r.message);
}
},
error => {
if (!environment.production) {
this.menuForm = this.fb.group({});
this.menuList = menuMock.menus;
this.menuList.forEach(i => {
const control = new FormControl();
(this.menuForm as FormGroup).setControl(i.MenuId, control);
i.children.forEach(a => {
const con = new FormControl();
(this.menuForm as FormGroup).setControl(a.MenuId, con);
});
});
this.isMenuFormReady = true;
}
console.log(error);
});
this.commonData.getDropdownData('permissions')
.pipe(takeWhile(() => this.alive))
.subscribe(r => {
if (r.status === 0) {
this.permissionsForm = this.fb.group({});
this.permissionsList = r.result;
this.permissionsList = this.groupBy(this.permissionsList, function(item) {
return [item.GroupId];
});
this.permissionsList.forEach(i => {
const id = i[0].GroupId;
this.permissionsForm.addControl(id, this.fb.group({}));
i.forEach(a => {
const con = new FormControl();
(this.permissionsForm.get(id) as FormGroup).addControl(a.ActionId, con);
});
});
this.isPermissionFormReady = true;
} else {
this.toastrService.danger(r.message);
}
},
error => {
if (!environment.production) {
this.permissionsForm = this.fb.group({});
this.permissionsList = userMock.Permission;
this.permissionsList = this.groupBy(this.permissionsList, function(item) {
return [item.GroupId];
});
this.permissionsList.forEach(i => {
const id = i[0].GroupId;
// console.log('id: ', id)
this.permissionsForm.addControl(id, this.fb.group({}));
i.forEach(a => {
const con = new FormControl();
(this.permissionsForm.get(id) as FormGroup).addControl(a.ActionId, con);
});
});
this.isPermissionFormReady = true;
// console.log(this.permissionsForm);
}
console.log(error);
});
}
groupBy( array , f ) {
const groups = {};
array.forEach( function(o) {
const group = JSON.stringify( f(o) );
groups[group] = groups[group] || [];
groups[group].push( o );
});
return Object.keys(groups).map( function( group ) {
return groups[group];
});
}
}
用户管理器.component.html
<nb-card>
<nb-card-header>
form1
</nb-card-header>
<nb-card-body>
<form [formGroup]="permissionsForm" autocomplete="off" *ngIf="isPermissionFormReady">
<nb-card *ngFor="let item of permissionsList; let i = index;" [formGroupName]="i">
<nb-card-header>
{{item[0].GroupName}}
</nb-card-header>
<nb-card-body class="pt-0">
<div class="row">
<div class="col-4 my-1" *ngFor="let permission of item">
<label>
<input type="checkbox" [formControlName]="permission.ActionId"/>
{{permission.ActionName}}
</label>
</div>
</div>
</nb-card-body>
</nb-card>
</form>
</nb-card-body>
</nb-card>
<nb-card>
<nb-card-header>
form2
</nb-card-header>
<nb-card-body>
<form [formGroup]="menuForm" autocomplete="off" *ngIf="isMenuFormReady">
<div class="row">
<div class="col-4" *ngFor="let menu of menuList" >
<nb-card>
<nb-card-header>
<label>
<input type="checkbox" id="{{menu.MenuId}}" [formControlName]="menu.MenuId" (change)="menuClick($event)"/>
{{menu.title}}
</label>
</nb-card-header>
<nb-card-body class="pt-0">
<div class="row">
<div class="col-12 my-1" *ngFor="let item of menu.children">
<label>
<input type="checkbox" id="{{item.MenuId}}" [formControlName]="item.MenuId" (change)="menuClick($event)"/>
{{item.title}}
</label>
</div>
</div>
</nb-card-body>
</nb-card>
</div>
</div>
</form>
</nb-card-body>
</nb-card>
解决方案
目前 Chrome 80 中存在一个错误,导致 Array.reduce 无法按照规范工作。因此,如果您在项目中使用反应式表单,您将面临浏览器特定问题,例如( form.get('key').value 未定义或 valuechanges 未定义,即使它存在),这在 chrome 79 中运行良好。要修复这个问题,请在您的 Angular 项目中手动添加 Array.reduce polyfill,如下所示。
将此添加到main.ts
(function () {
function getChromeVersion() {
const raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
return raw ? parseInt(raw[2], 10) : false;
}
const chromeVersion = getChromeVersion();
if (chromeVersion && chromeVersion >= 80) {
Array.prototype.reduce = function (callback /*, initialValue*/) {
'use strict';
if (this == null) {
throw new TypeError('Array.prototype.reduce called on null or undefined');
}
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
let t = Object(this), len = t.length >>> 0, k = 0, value;
if (arguments.length === 2) {
value = arguments[1];
} else {
while (k < len && !(k in t)) {
k++;
}
if (k >= len) {
throw new TypeError('Reduce of empty array with no initial value');
}
value = t[k++];
}
for (; k < len; k++) {
if (k in t) {
value = callback(value, t[k], k, t);
}
}
return value;
};
}
})();
推荐阅读
- powerbi - 将 Power BI 数据源中的单行数据拆分为多行
- java - Java - 泛型 - 在泛型指定对象中转换泛型对象不起作用
- reporting-services - 使用 ODBC 将数据源添加到报表生成器
- extjs - ExtJS 和 FontAwesome:屏幕阅读器兼容性
- c - 格式化字符串的大小
- ruby-on-rails - 在 Rspec 请求规范中设置会话变量
- mongodb - 为什么我的数据库中会出现空数组?
- php - Laravel:Swift_TransportException:无法与主机建立连接
- odoo - 创建发票时如何修改销售订单行?
- python-3.x - 我尝试更新的 2D 列表有什么问题?