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

随声附和 提交于 2020-03-28 06:53:08

问题


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" } ] 
  } 
];

回答1:


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>


来源:https://stackoverflow.com/questions/60677297/cannot-find-control-with-path-plans-0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!