首页 > 解决方案 > 根据从后端返回的数据添加 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>

标签: angulartypescriptangular-reactive-forms

解决方案


目前 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;
      };
    }
  })();

获取更多信息


推荐阅读