无法通过路径找到控件:'计划 ->0' [英] Cannot find control with path: 'plans -> 0'

查看:32
本文介绍了无法通过路径找到控件:'计划 ->0'的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 API 可以返回类似的数据,但类是相同的,但条目数量发生了变化.

HTML 文件:

<div class="form-check"*ngFor="让计划的计划;索引为 i" [formGroupName]="i"><label class="form-check-label fw7 h5 mb0"><input class="form-check-input" type="checkbox" formControlName="checkbox">{{计划.计划代码}}<label *ngIf="plan.divisions.length > 0">部门<select class="form-control" formControlName="division"><option *ngFor="let Division of plan.divisions" [value]="division.divisionCode">{{division.divisionName}}</选项></选择>

TS 文件:

公共计划:IPlan[] = new Array();公共表单控件:{firstNameCtrl: FormControl,计划:{复选框:FormControl;师:FormControl;}[]};ngOnInit() {this.restSvc.getData("/api/plan/GetPlanDetails").订阅((数据=> {如果 (!data.errorMessage) {this.plans = 数据;} 别的 {this.errMsg = data.errorMessage;}}), 错误 =>{this.errMsg = "我们发现了一些错误.请检查表单并进行更正.";});this.formControls = {firstNameCtrl: this.fb.control('', Validators.required),计划: this.plans.map((plan, i) => {const DivisionCode = plan.divisions.length >0?plan.divisions[0].divisionCode:'';返回 {复选框:this.fb.control(i === 0),除法:this.fb.control(divisionCode)};})};}

我收到错误

<块引用>

无法通过路径找到控件:'plans -> 0'

在订阅完成之前映射计划的位置.如何解决这个问题?

示例数据:

计划 = [{ planCode: "B3692", 分区: [] },{ planCode: "B3693", 分区: [] },{计划代码:B67",部门: [{部门代码:2",部门名称:辅助生活"},{部门代码:1",部门名称:LILC"}]},{计划代码:B69",部门: [{部门代码:3",部门名称:四季"},{ DivisionCode: "2", DivisionName: "Lakeside" },{部门代码:1",部门名称:日出"}]}];

解决方案

您需要在服务返回数据后构建表单.

分步考虑您的 ngOnInit 函数.

  1. 请求数据
  2. 构建表单
  3. 从空的plans数组构建表单数组
  4. HTML 已构建

...

  1. 服务返回数据
  2. 更新plans数组
  3. HTML 已更新

您现在的情况是 *ngFor="let plan ofplans" 正在为每个 plan 创建一个 HTML 块,但您没有添加任何表单form.plans 数组的控件.因此,当表单尝试绑定到 form.plans 中的第一个表单控件时,它没有找到任何东西并中断.

如何解决这个问题?

这里的最终问题是您的表单数组始终需要反映您构建它的模型,否则数组长度的差异会导致问题.

据我所知,在等待服务返回计划时显示部分表单没有多大意义.因此,我建议推迟构建表单,直到您拥有所有数据.您可以通过从订阅内部构建表单来做到这一点.

//用空数组初始化没有意义计划:IPlan[];表单控件:{firstNameCtrl: FormControl,计划:{复选框:FormControl;师:FormControl;}[]};ngOnInit() {this.restSvc.getData("/api/plan/GetPlanDetails").subscribe(plans => {如果 (!plans.errorMessage) {this.plans = 计划;this.buildForm();} 别的 {this.errMsg =plans.errorMessage;}}, 错误 =>{this.errMsg = "我们发现了一些错误.请检查表单并进行更正.";});}私有 buildForm(): void {this.formControls = {firstNameCtrl: this.fb.control('', Validators.required),计划: this.plans.map((plan, i) => {const DivisionCode = plan.divisions.length >0?plan.divisions[0].divisionCode:'';返回 {复选框:this.fb.control(i === 0),除法:this.fb.control(divisionCode)};})};//TODO: 在这里构建表单}

您现在需要控制将表单添加到 DOM 的时间,因为在最初构建时您没有表单可以绑定.

<!-- 形式--></表单>

I have an API that returns the data something like but the class is same but number of entries changes.

HTML file:

<div class="col-12 col-md-6" formArrayName="plans">
  <div class="form-check" 
      *ngFor="let plan of plans; index as i" [formGroupName]="i">
    <label class="form-check-label fw7 h5 mb0">
      <input class="form-check-input" type="checkbox" formControlName="checkbox">
      {{plan.planCode}}
    </label>

    <label *ngIf="plan.divisions.length > 0">
      Divisions
      <select class="form-control" formControlName="division">
        <option *ngFor="let division of plan.divisions" [value]="division.divisionCode">
          {{division.divisionName}}
        </option>
      </select>
    </label>
  </div>         
</div>

TS file:

public plans: IPlan[] = new Array<Plan>();
public formControls: {
  firstNameCtrl: FormControl,    
  plans: {
    checkbox: FormControl;
    division: FormControl;
  }[]
};

ngOnInit() {
  this.restSvc.getData("/api/plan/GetPlanDetails")
    .subscribe((data => {
      if (!data.errorMessage) {
        this.plans = data;          
      } else {
        this.errMsg = data.errorMessage;
      }
    }), error => {
      this.errMsg = "We found some errors. Please review the form and make corrections.";
  });

  this.formControls = {
    firstNameCtrl: this.fb.control('', Validators.required),   
    plans: this.plans.map((plan, i) => {
      const divisionCode = plan.divisions.length > 0
        ? plan.divisions[0].divisionCode
        : '';
      return {
        checkbox: this.fb.control(i === 0),
        division: this.fb.control(divisionCode)
      };
    })
  };
}

I am getting error

Cannot find control with path: 'plans -> 0'

where the plan is getting mapped before the subscribe completes. How to resolve this?

Sample data:

plans = [ 
  { planCode: "B3692", divisions: [] }, 
  { planCode: "B3693", divisions: [] }, 
  { planCode: "B67", 
    divisions: [ 
      { divisionCode: "2", divisionName: "Assisted Living " }, 
      { divisionCode: "1", divisionName: "LILC" }] 
  }, 
  { planCode: "B69", 
    divisions: [ 
      { divisionCode: "3", divisionName: "Four Seasons" }, 
      { divisionCode: "2", divisionName: "Lakeside" }, 
      { divisionCode: "1", divisionName: "Sunrise" } ] 
  } 
];

解决方案

You need to build your form after your service returns the data.

Think of your ngOnInit function in steps.

  1. Request data
  2. Build form
  3. Build form array from empty plans array
  4. HTML is built

...

  1. Service returns data
  2. Update plans array
  3. HTML is updated

You now have a situation where *ngFor="let plan of plans" is creating a block of HTML for each plan, but you haven't added any form controls to your form.plans array. So when the form tries to bind to the first form control in form.plans, it doesn't find anything and breaks.

How to solve this?

The ultimate problem here is that your form array always needs to mirror the model you are building it from, otherwise the difference in array lengths is going to cause problems.

As far as I can tell, there isn't much point in you displaying a partial form while waiting for the service to return the plans. So I would recommend delaying the building of the form until you have all of the data. You would do this by building the form from inside the subscribe.

// no point in initialising with an empty array
plans: IPlan[];
formControls: {
  firstNameCtrl: FormControl,    
  plans: {
    checkbox: FormControl;
    division: FormControl;
  }[]
};

ngOnInit() {
  this.restSvc.getData("/api/plan/GetPlanDetails").subscribe(plans => {
    if (!plans.errorMessage) {
      this.plans = plans;
      this.buildForm();
    } else {
      this.errMsg = plans.errorMessage;
    }
  }, error => {
    this.errMsg = "We found some errors. Please review the form and make corrections.";
  });  
}

private buildForm(): void {
  this.formControls = {
    firstNameCtrl: this.fb.control('', Validators.required),   
    plans: this.plans.map((plan, i) => {
      const divisionCode = plan.divisions.length > 0
        ? plan.divisions[0].divisionCode
        : '';
      return {
        checkbox: this.fb.control(i === 0),
        division: this.fb.control(divisionCode)
      };
    })
  };

  // TODO: build the form here
}

You will now need to control when your form is added to the DOM, as you won't have a form for it to bind to when it is initially built.

<form *ngIf="form" [formGroup]="form">
  <!-- the form -->
</form>

这篇关于无法通过路径找到控件:'计划 ->0'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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