Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 角度5/4+;:使用API调用填充嵌套的ReactiveForm_Angular_Typescript_Mean Stack - Fatal编程技术网

Angular 角度5/4+;:使用API调用填充嵌套的ReactiveForm

Angular 角度5/4+;:使用API调用填充嵌套的ReactiveForm,angular,typescript,mean-stack,Angular,Typescript,Mean Stack,我正在尝试填充嵌套的ReactiveForm,它被拆分为几个子表单组件。一旦API请求完成,我就可以填充父表单,但不能将子FormArray精确循环到子数据的计数。以下是我的代码片段: 编辑视图:编辑.component.ts @Component({ selector: 'app-edit', templateUrl: './edit.component.html', styleUrls: ['./edit.component.scss'] }) export class Edit

我正在尝试填充嵌套的
ReactiveForm
,它被拆分为几个子表单组件。一旦API请求完成,我就可以填充父表单,但不能将子
FormArray
精确循环到子数据的计数。以下是我的代码片段:

编辑视图:编辑.component.ts

@Component({
  selector: 'app-edit',
  templateUrl: './edit.component.html',
  styleUrls: ['./edit.component.scss']
})
export class EditComponent implements OnInit {

  public data: Service = new Service({
            id: '',
            title: '',
            description: '',
            service_extras: []
        });    
  public routeParams: any = {};    
  constructor ( 
    private route: ActivatedRoute,
    private service: ServicesService
  ) { }

  ngOnInit() {
    this.setRouteParams();
  }

  setRouteParams() {
    this.route.params.subscribe(params => {
        this.routeParams = params;
      // getting services using api call
        this.getService(this.routeParams);
    });
  }

  getService(params) {
    this.service
    .getService(params.id)
    .subscribe((service: Service) => {
        this.data = service;
    });
  }

}
@Component({
    selector: 'service-form',
    templateUrl: './service-form.component.html',
    styleUrls: ['./service-form.component.scss']
})
export class ServiceFormComponent implements OnInit {

    private _serviceFormData = new BehaviorSubject<Service>(null);    
    @Input()
    set serviceFormData(value) {
        this._serviceFormData.next(value);
    }        
    get serviceFormData() {
        return this._serviceFormData.getValue();
    }    
    public service: Service;
    public serviceForm: FormGroup;

    constructor(
        private fb: FormBuilder
    ) { }

    ngOnInit() {    
        this.serviceForm = this.toFormGroup();
        this._serviceFormData.subscribe(data => {
            this.serviceForm.patchValue(data);
        });
    }

    private toFormGroup(): FormGroup {           
        const formGroup = this.fb.group({
            id: [ '' ],
            title: [ '' ],
            description: [ '' ]
        });    
        return formGroup;
    }
}
@Component({
  selector: 'service-extra-form',
  templateUrl: './service-extra.component.html',
  styleUrls: ['./service-extra.component.scss']
})
export class ServiceExtraComponent implements OnInit {    
  private _extraFormData = new BehaviorSubject<ServiceExtra[]>([]);

  @Input() serviceForm: FormGroup;    
  @Input() 
  set extraFormData(value: ServiceExtra[]) {
    this._extraFormData.next(value);
  }    
  get extraFormData() {
    return this._extraFormData.getValue();
  }

  public extrasForm: FormGroup;

  constructor(private fb: FormBuilder) { }

  ngOnInit()
  {
    this.serviceForm.addControl('service_extras', new FormArray([]));    
    this._extraFormData.subscribe(data => {
      this.addNew();
      this.extras.patchValue(data);
    });

  }

  private toFormGroup()
  {
    const formGroup = this.fb.group({
      id: [''],
      service_id: [''],
      title: ['']
    });    
    return formGroup;
  }

  public addNew()
  {
    this.extrasForm = this.toFormGroup();        (<FormArray>this.serviceForm.controls.service_extras).push(this.extrasForm);
  }

  public removeThis(i: number)
  {
    (<FormArray>this.serviceForm.controls.service_extras).removeAt(i);
  }


  get extras(): FormArray {
     return this.serviceForm.get('service_extras') as FormArray;
  }

}
我正在请求base
edit.component.ts
component中的数据,并将接收到的数据传递给父表单组件,该组件是
EditComponent

edit.component.html

<service-form [serviceFormData]="data"></service-form>
上面的
ngOnInit
code只添加一个附加表单(即使有两条记录)并填充该表单,即使我删除订阅部分并仅使用
this.addNew()
,这种情况也是一样的。我如何知道
ServiceExtras
有多少条记录,以便我可以将这些
FormGroups
添加到
FormArray

编辑1

闪电战

编辑2

问题是,如果有两条来自API的记录用于service extra,那么我无法生成两个
FormGroups
并用数据填充它们,因为在呈现时,我无法检测有多少条来自API的service extras记录。

这里有一个修复(stackblitz)

对问题行为的解释:

您的输入是这样声明的:

<service-extra-form [serviceForm]="serviceForm" [extraFormData]="serviceForm.value.service_extra"></service-extra-form>
带有
数据=未定义的

它在formArray中创建一个新的formGroup,然后使用undefined进行修补

因此,当API响应时,您的表单已经使用包含一个项的formArray创建,因此
patchValue
截断您的服务\u额外数组以匹配您的表单

纠正方法是将API的返回直接绑定为
ServiceExtraComponent
Input
aka:

<service-extra-form [serviceForm]="serviceForm" [extraFormData]="serviceFormData.service_extras"></service-extra-form>

服务表单.component.html
中,您将
服务表单.value.service\u extras
属性绑定到
extraFormData
。但是在
服务附加表单
组件初始化之前
服务表单
没有服务附加表单格式。在初始化之后。在
服务额外表单
组件中,您调用
addRow()
方法,该方法精确地用一行填充表单:

服务附加组件.ts

 ngOnInit()
  {
    this.serviceForm.addControl('service_extras', new FormArray([]));    
    this._extraFormData.subscribe(data => {
      console.log('service_extra_data', data);
      this.addNew();
      this.extras.patchValue(data);
    });

  }
服务表单.component.html:

<service-extra-form [serviceForm]="serviceForm" 
                    [extraFormData]="serviceForm.value.service_extras">
 </service-extra-form> 

将[serviceForm]传递给
服务额外表单
就足够了。如果您已经通过了
表单
,为什么要通过
serviceForm.value.service\u extras


固定,移除额外的代码。用更少的代码做同样的事情你能在stackblitz上演示你的问题吗?@yurzui我已经编辑了我的问题来添加stackblitz演示检查代码,但我仍然不明白问题出在哪里。你想什么时候知道临时服务有多少条记录?你想计数吗@trungk18实际上,问题是如果他们的两条记录是为额外服务而来的,那么它只填充了一条记录,这是因为我将1个表单组推到了额外服务中。。。我的问题是我无法检测到有多少额外的服务记录来自API,这样我就可以生成那些
表单组
,并将其推送到
服务额外
,这是有意义的吗?感谢您的回答,我将查看答案并让您知道。解决方案对我有效,另外,@PierreMallet提供的解决方案也很好。我现在搞不清楚哪一个被接受,哪一个被授予赏金。真的很感激你的宝贵经验inputs@SagarGuhe,很乐意帮忙✌这个解决方案对我有效,@Yerkon提供的解决方案也很有效。我现在搞不清楚哪一个被接受,哪一个被授予赏金。我真的很感谢你的宝贵意见。
<service-extra-form [serviceForm]="serviceForm" 
                    [extraFormData]="serviceForm.value.service_extras">
 </service-extra-form>