以角度形式修补值

Posted

技术标签:

【中文标题】以角度形式修补值【英文标题】:Patch the values in angular form 【发布时间】:2019-04-12 17:02:55 【问题描述】:

我正在使用 angular 6 制作应用程序,我使用的是 angular 动态形式。

在创建表单并提交时,我已经完成了所有工作,您可以看到正在运行的 stackblitz,https://stackblitz.com/edit/angular-x4a5b6-hne6fg

仅供参考:此表单有子元素,它们将被打开并在单击添加按钮时附加,并在单击删除按钮时逐个删除..

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

假设我将 get service 称为,

    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)
     )

我正在尝试将值修补到您可以在 stacblitz 的 dynamic-form.ts 中看到的表单中,

  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 具有 value 作为新模板,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会被绑定..

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

【问题讨论】:

【参考方案1】:

在https://stackblitz.com/edit/angular-x4a5b6-xcychx?file=src%2Fapp%2Fdynamic-form.component.html 中,我将其作为“路径值”。

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

  //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 有问题(关于将 propertyOrigin 转换为一系列复选框的问题,让我有时间 - 我稍后会更新这个答案 -)

更新 见stackblitz updated 创建新的问题类型以创建复选框列表 复选框有问题。在 Angular 中,一个复选框只能有两个值“真”或“假”。在我知道之前,属性值没有影响。

所以,我们不能做出类似的东西

<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

一项工作是创建一个新的 QuestionType "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 "]。我们必须使用地图

更新 看一下question-control-service的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))
      
    

【讨论】:

查看我的更新答案。对不起,我赶时间,最后一部分(将数据转换为表格,将表格转换为数据未解决。希望您能做到或回答社区并有人可以帮助您) @ManiRaj,我更新了 stackblitz stackblitz.com/edit/…。有几处改动,所以我加了一个README.txt解释代码。我想你有不同的“json”,一个用于模型,一个用于数据,但我不确定你是否真的有一个独特的 json,数据和模型连接在一起。在这种情况下,必须更改代码 我想我终于明白了。在stackblitz.com/edit/… 中,您有一个由混合数据和模型的独特 jsonData 提供的动态表单供稿 @Mai 我更新了答案。关键是理解函数foFormGroup。有一个“奇怪的步骤”是给孩子们一个新的属性:“controlType”,需要显示控件 我的解释不好。您必须添加我指出的行,但不要删除函数的所有其余部分,请参阅我的 stackblitz.com/edit/angular-x4a5b6-28ysqg?file=src/app/…【参考方案2】:

使用patchValue设置表格数据

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

【讨论】:

还有template_properties 会发生什么,因为它在单击添加按钮时打开,但在此修补期间,它需要自动打开并且需要填充template_properties 的相应数据。

以上是关于以角度形式修补值的主要内容,如果未能解决你的问题,请参考以下文章

使用ngModel指令以角度形式获取所有值

以角度形式形成输入数组

如何将元素更改为以角度形式输入或下拉?

使用 formcontrol 将数据绑定到角度材料表中的复选框。数据以真假值列表的形式提供

如何以角度形式实现条件要求验证?

无法以角度反应形式添加验证器