修补 angular 形式的值

Patch the values in angular form

我正在使用 angular 6 制作应用程序,我正在使用 angular 动态表单。

至于创建表单并提交我已经完成了所有事情,您可以看到工作 stackblitzhttps://stackblitz.com/edit/angular-x4a5b6-hne6fg

仅供参考:此表单包含子元素,这些子元素将在单击“添加”按钮时打开并追加,并在单击“删除”按钮时逐个删除。

我需要的是,我只需要在编辑每一行的过程中分别通过服务将值修补到每个输入..

假设我调用 get 服务 作为,

    this.dynamicFormService.getRest(url,token).subscribe(res => {
        this.form.value = res.data;   //Tried this line but got error (Cannot assign to 'value' because it is a constant or a read-only property)
     })

我正在尝试将值修补为您可以在 dynamic-form.ts in stacblitz,

中看到的形式
  ngOnInit() {
    this.form = this.qcs.toFormGroup(this.questions);
}

如果我将表单设置为 console.log(this.form.value),它给出的结果是

template_desc: ""
template_name: ""
template_properties: Array(0)
length: 0
__proto__: Array(0)

console.log(res.data)在获取服务结果中给出,

data:
template_obj_id: "123"
template_desc: "New template description"
template_name: "New Template"
template_properties: Array(1)
0:
property_name: "Property name"
property_origin: ["VBM"]
property_required: true
property_type: "Property type"

我只需要将来自 res.data 的数据绑定到所有表单输入中。

这些是我需要分别修补到所有输入的值,例如 template_name 具有 作为新模板和 template_desc 作为 New template description等..

对于 template_properties 值还有另一个重要的事情,即数组将在创建期间单击添加按钮时打开,而在编辑期间它应该自动打开并显示 template_properties 中的行数..

虽然问题有点大了解释,我需要的东西是单一的..我需要修补来自服务的数据(res.data) 分别添加到每个表单元素,包括 template_properties 在内的所有表单元素都需要可见,用户可以在其中编辑和提交表单。

res.data、

的截图

尝试了以下答案,

 this.form.patchValue({
      template_desc: res.data.template_desc,
      template_name:  res.data.template_name,
    });

但是如果我给出 template_properties: res.data.template_properties,模板属性不会被绑定但是其他两个 template name and desc 会被绑定..

请帮助实现数据到表单元素的修补...

使用patchValue设置数据形成

this.dynamicFormService.getRest(url,token).subscribe(res => {
   this.form.patchValue({
      template_desc: res.data.template_desc,
      template_name:  res.data.template_name,
    });
 }

https://stackblitz.com/edit/angular-x4a5b6-xcychx?file=src%2Fapp%2Fdynamic-form.component.html中,我输入为"path the values".

唯一需要考虑的是,您需要像数组一样将元素添加到表单中。

  //This function serve to add to the array the elments of the arrays
  //Is the same that we use when add a new line to the Array Form
  addControls(control: string) {
    let question: any = this.questions.find(q => q.key == control);
    let children = question ? question.children : null;
    if (children)
      (this.form.get(control) as FormArray).push(this.qcs.toFormGroup(children))
  }
  this.dynamicFormService.getRest(url,token).subscribe(res => {
        //In res.data you have the data.
        //In res.dat.template_properties you has the array

        //Create the Form
        this.form = this.qcs.toFormGroup(this.questions);
        //Add so element at array as was necesary
        for (let i=0;i<this.data.myArray.length;i++)
        {
            this.addControls('template_properties')
        }
        //Finally use patchValue
        this.form.patchValue(res.data);
    }

好吧,你的数据与 this.questions 不对应,而且你的 property_origin 有问题(关于 as convert propertyOrigin to series of checkBox 的问题,等我一段时间 -I'稍后我会更新这个答案-)

已更新stackblitz updated 创建一个新的问题类型以创建一个复选框列表 复选框有问题。在 Angular 中,一个复选框只能有两个值 "true" 或 "false"。直到我知道,属性值没有影响。

所以,我们不能做出类似

的东西
<input type="checkbox" value="car" formControlName="checkName">
<input type="checkbox" value="dog" formControlName="checkName">

要在 "checkName" 中获取一个数组 ['car','dog'] 如果您检查了这两个值。

我们如何解决这个问题?我认为更好的主意是有一个像

这样的 formGroup
<div formGroupName="checkName">
  <input type="checkBox" formControlName="car">
  <input type="checkBox" formControlName="dog">
</div>

所以,我们会得到一些像

   checkName={car:true,dog:false}

好吧,一个工作是制作一个新的问题类型"ListCheckBoxQuestion"

export class ListCheckBoxQuestion extends QuestionBase<string> {
  controlType = 'list-chekbox';
  options: {key: string, value: string}[] = [];

  constructor(options: {} = {}) {
    super(options);
    this.options = options['options'] || [];
  }
}

之后我们可以更改dinamic-formquestion.component添加一个新的开关。看到我们使用 question.key 创建了一个 formGroupName,并且在这个组中我们使用 "options"

创建了一个 formControlName
<div [formGroupName]="question.key"  *ngSwitchCase="'list-chekbox'" >
  <ng-container *ngFor="let opt of question.options">
  <input type="checkbox"  [formControlName]="opt.key">
                <label >{{opt.value}}</label>
  </ng-container>
</div>

嗯,最难的部分是我们创建表单(question-control-service 的 toFormGroup 函数

toFormGroup(questions: QuestionBase<any>[]) {
    let group: any = {};

    questions.forEach(question => {
      if (question.controlType=="array") {
         group[question.key]=new FormArray([]);
      }else if (question.controlType=="list-chekbox")
      { //We create a FromGroup using the options
        let controls:any={};
        for (let option of question.options)
             controls[option.key]=new FormControl(false);
        group[question.key]=new FormGroup(controls);
        console.log("*",question);
      }
      else {
       ...
      }
    });
    return new FormGroup(group);
  }

好吧,有一项工作是将我们的 form.value 转换为数据,并将接收到的数据转换为 form.value。

当我们收到类似 ["car","dog"] 的内容时,我们必须转换为 {car:true,dog:true},当我们有 {car:true,dog:false} 时,我们必须转换为 ["car"]。我们必须使用 map

更新 看一下问题控制服务的 toFormGroup 函数。该函数是创建表单的函数。在上一个版本中,我们将许多行添加到数组中作为值长度。如果没有指定值,则更改此功能以添加线条

questions.forEach(question => {
      if (question.controlType == "array") {
        group[question.key] = new FormArray([]);
        if (question.value) {
          if (question.children) {
            //If question.children we must to give "value" to the children
            //So the children has as value, the value given in dataArray
            for (let value of question.value) {
              Object.keys(value).forEach(key => {
                let qu = question.children.find(x => x.key == key)
                if (qu) {
                  qu.value = value[key];
                  qu.controlType = qu.elementType
                }
              })
              group[question.key].push(this.toFormGroup(question.children))
            }
          }
        } //Add this lines to add one line to the array if no 
          //value is indicated
    else {
      if (question.children) {
        question.children.forEach(qu => {
          qu.controlType = qu.elementType

        })
        group[question.key].push(this.toFormGroup(question.children))
      }
    }