根据后端返回的数据添加 FormControl,但在 Angular 应用程序中出现两个不同的错误 [英] Add FormControl accroding to the data returned from backend but got two different error in Angular app

查看:14
本文介绍了根据后端返回的数据添加 FormControl,但在 Angular 应用程序中出现两个不同的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的 Angular 应用的页面之一.

在 ngOnInit 方法中,我调用 api 两次以获取我需要的不同数据,并使用 forEach 方法循环数据以构建反应式表单,但不知何故,我遇到了两种不同的错误之一.

这个

在此处输入图片说明

还有这个

在此处输入图片描述

有时根本没有错误.

如果有人能告诉我我的代码有什么问题,我们将不胜感激.

这是我的代码的一部分

user-manager.component.ts

导出类 UserManagerComponent 实现 OnInit {构造函数(私人 fb:FormBuilder) {}ngOnInit(): 无效 {this.commonData.getDropdownData('menus').pipe(takeWhile(() => this.alive)).订阅(r => {如果(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;} 别的 {this.toastrService.danger(r.message);}},错误 =>{如果(!环境.生产){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;}控制台日志(错误);});this.commonData.getDropdownData('权限').pipe(takeWhile(() => this.alive)).订阅(r => {如果(r.status === 0){this.permissionsForm = this.fb.group({});this.permissionsList = r.result;this.permissionsList = this.groupBy(this.permissionsList, function(item) {返回 [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;} 别的 {this.toastrService.danger(r.message);}},错误 =>{如果(!环境.生产){this.permissionsForm = this.fb.group({});this.permissionsList = userMock.Permission;this.permissionsList = this.groupBy(this.permissionsList, function(item) {返回 [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);}控制台日志(错误);});}groupBy( 数组, f ) {常量组 = {};array.forEach(函数(o){const group = JSON.stringify( f(o) );组[组] = 组[组] ||[];组[组].push(o);});返回 Object.keys(groups).map(function(group){返回组[组];});}}

user-manager.component.html

 <nb-card-header>表格1</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="让项目的权限"><标签><input type="checkbox" [formControlName]="permission.ActionId"/>{{permission.ActionName}}

</nb-card-body></nb-card></表单></nb-card-body></nb-card><nb卡><nb-card-header>表格2</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卡><nb-card-header><标签><input type="checkbox" id="{{menu.MenuId}}" [formControlName]="menu.MenuId" (change)="menuClick($event)"/>{{menu.title}}</nb-card-header><nb-card-body class="pt-0"><div class="row"><div class="col-12 my-1" *ngFor="let item of menu.children"><标签><input type="checkbox" id="{{item.MenuId}}" [formControlName]="item.MenuId" (change)="menuClick($event)"/>{{item.title}}

</nb-card-body></nb-card>

</表单></nb-card-body></nb-card>

解决方案

目前 Chrome 80 中存在一个错误,导致 Array.reduce 无法按照规范工作.因此,如果您在项目中使用反应式表单,您将面临浏览器特定的问题,例如( form.get('key').value 未定义或 valuechanges 未定义,即使它存在),这在 chrome 79 中工作正常.要修复这个问题,在你的 angular 项目中手动添加 Array.reduce polyfill,如下所示.

将此添加到 ma​​in.ts

(函数(){函数 getChromeVersion() {const raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);返回原始 ?parseInt(raw[2], 10) : 假;}const chromeVersion = getChromeVersion();如果 (chromeVersion && chromeVersion >= 80) {Array.prototype.reduce = 函数(回调/*,initialValue*/){'使用严格';如果(这个 == 空){throw new TypeError('Array.prototype.reduce call on null or undefined');}如果(回调类型!=='函数'){throw new TypeError(callback + ' is not a function');}让 t = Object(this), len = t.length >>>0,k = 0,值;if (arguments.length === 2) {值 = 参数 [1];} 别的 {而 (k < len && !(k in t)) {k++;}如果 (k >= len) {throw new TypeError('减少没有初始值的空数组');}值 = t[k++];}for (; k 

更多信息

This is one of the page of my Angular app.

Inside the ngOnInit method, I call the api twice to get different data I need and loop through the data by using forEach method to build reactive form, but somehow, I encountered one of two different error.

This

enter image description here

and this

enter image description here

and sometime there is no error at all.

It would be grateful if someone can tell me what's wrong with my code.

here is part of my code

user-manager.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];
        });
    }
}

user-manager.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>

解决方案

There is currently a bug in Chrome 80 which makes Array.reduce not to work according to the spec. So If you are using reactive form in your project you will face browser specific issue like ( form.get('key').value is undefined or valuechanges is undefined even if it exists), which was working fine in chrome 79. To fix this issue, add Array.reduce polyfill in your angular project manually as shown below.

Add this to 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;
      };
    }
  })();

ForMoreInfo

这篇关于根据后端返回的数据添加 FormControl,但在 Angular 应用程序中出现两个不同的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆