【问题标题】:Form element values as JSON using angular form使用角度形式将元素值形成为 JSON
【发布时间】:2019-04-06 10:13:34
【问题描述】:

我正在使用 Angular dynamic form 制作 Angular 6 应用程序

在这里我做了一个嵌套输入字段,在初始阶段将有两个输入文本框,点击添加按钮后,接下来的两个输入框将在每次点击添加按钮时追加。

这里一切正常。

这里我使用了 question-service.ts 中的值,

  new TextboxQuestion({
  elementType: "textbox",
  class: "col-12 col-md-4 col-sm-12",
  key: "project_name",
  label: "Project Name",
  type: "text",
  value: '',
  required: true,
  order: 1
  }),

  new TextboxQuestion({
  elementType: "textbox",
  class: "col-12 col-md-4 col-sm-12",
  key: "project_desc",
  label: "Project Description",
  type: "text",
  value: '',
  required: true,
  order: 2
  }),
  new ArrayQuestion({
    key: 'myArray',
    value: '',
    order: 3,
    children: [
      new TextboxQuestion({
      elementType: "textbox",
      class: "col-12 col-md-4 col-sm-12",
      key: "property_one",
      label: "Property One",
      type: "text",
      value: '',
      required: true,
      order: 3
      }),
      new TextboxQuestion({
      elementType: "textbox",
      class: "col-12 col-md-4 col-sm-12",
      key: "property_two",
      label: "Property Two",
      type: "text",
      value: '' ,
      required: true,
      order: 4
      })
    ]
  })

我需要更改的数据应该来自每个赞的 json,

  jsonData: any = [
    {
      "elementType": "textbox",
      "class": "col-12 col-md-4 col-sm-12",
      "key": "project_name",
      "label": "Project Name",
      "type": "text",
      "value": "",
      "required": true,
      "order": 1
    },
    {
      "elementType": "textbox",
      "class": "col-12 col-md-4 col-sm-12",
      "key": "project_desc",
      "label": "Project Description",
      "type": "text",
      "value": "",
      "required": true,
      "order": 2
    },
    {
      "elementType": "array",
      "key": "myArray",
      "value": "",
      "order": "3",
      "children": [
        {
          "elementType": "textbox",
          "class": "col-12 col-md-4 col-sm-12",
          "key": "property_one",
          "label": "Property One",
          "type": "text",
          "value": "",
          "required": true,
          "order": 3
        },
        {
          "elementType": "textbox",
          "class": "col-12 col-md-4 col-sm-12",
          "key": "property_two",
          "label": "Property Two",
          "type": "text",
          "value": "",
          "required": true,
          "order": 4
        }
      ]
    }
  ];

Stackblitz 没有 JSON:

https://stackblitz.com/edit/angular-x4a5b6-xcychx

Stackblitz 使用 JSON:

https://stackblitz.com/edit/angular-x4a5b6-u6ecpk

加载 JSON 时需要发生在没有 json 的 stacblitz 链接中发生的相同场景..

我在getQuestions()里面给出了如下的赞,

 getQuestions() {

    console.log(this.jsonData);

    let questions: any = [];

    this.jsonData.forEach(element => {
      if (element.elementType === 'textbox') {
        questions.push(new TextboxQuestion(element));
      } else if (element.elementType === 'array') {
        questions.push(new ArrayQuestion(element));
      }
    });

    return questions.sort((a, b) => a.order - b.order);
  }
}

对于普通文本框,它可以正常工作,但对于子文本框,它无法单击添加按钮(文本框未显示),子文本框不会被添加。

请帮助我实现link 1 中发生的相同结果,同时在link 2 中使用 JSON 时也需要发生 .. 并且请不要在所有内容中包含任何第三方库,所有内容都以核心角度进行。

【问题讨论】:

    标签: javascript json angular typescript angular-reactive-forms


    【解决方案1】:

    您必须添加一个新类型“复选框”

    export class CheckBoxQuestion extends QuestionBase<string> {
      controlType = 'checkbox';
      type: boolean;
    
      constructor(options: {} = {}) {
        super(options);
      }
    }
    

    并更改动态表单问题

    <div [formGroup]="form">
        <!--the label only show if it's NOT a checkbox --->
        <label *ngIf="question.controlType!='checkbox'" [attr.for]="question.key">{{question.label}}</label>
    
      <div [ngSwitch]="question.controlType">
        ...
        <!--add type checkbox-->
        <ng-container *ngSwitchCase="'checkbox'">
        <input  [formControlName]="question.key" type="checkbox"
                [id]="question.key" >
                    <label [attr.for]="question.key">{{question.label}}</label>
    
                </ng-container>
        ...
      </div> 
    

    并询问服务以考虑新的复选框

    else if (e.elementType === 'checkbox') {
                children.push(new CheckBoxQuestion(e));
              }
    

    更新 如果我们想添加更多验证器,请查看 question.service.ts 的“toFormGroup”函数

    toFormGroup(questions: QuestionBase<any>[]) {
        let group: any = {};
    
        questions.forEach(question => {
          if (question.controlType=="array") {
             group[question.key]=new FormArray([]);
          }
          else {
            //create an array of "validators"
            let validators:any[]=[];
            //If question.required==true, push Validators.required
            if (question.required && question.controlType!='checkbox')
                validators.push(Validators.required);
            //...add here other conditions to push more validators...
            group[question.key] = new FormControl(question.value || '',validators);
          }
        });
        return new FormGroup(group);
      }
    

    更新两个 也需要更改 questionbase.ts 以添加此属性

    export class QuestionBase<T> {
      value: T;
      ...
      maxlength:number;
      minlength:number;
    
      constructor(options: {
          value?: T,
          ....
          minlength?:number,
          maxlength?:number,
          controlType?: string,
          children?:any
        } = {}) {
        this.value = options.value;
        ....
        this.minlength = options.minlength;
        this.maxlength = options.maxlength;
        ...
      }
    }
    

    要查看您必须与 form.get(question.key).errors 相关的错误,例如

      <div class="errorMessage" 
         *ngIf="form.get(question.key).errors?.required">
        {{question.label}} is required
      </div>
    

    提示:为了了解您的错误,请使用

    {{form.get(question.key).errors|json}}
    

    forked stackblitz

    【讨论】:

    • 为什么它返回布尔值而不是 JSON 中作为值给出的字符串?复选框可能是多个复选框,但通常它只会返回值知道吗? w3schools.com/tags/tryit.asp?filename=tryhtml_input_checked
    • 请在这两种情况下帮助我 1) 虽然我使用返回布尔值 true 或 false 的复选框,但在初始阶段我给出了 [checked]="true" 但我看不到 @ 987654331@ 为property_check,但复选框已选中.. 而如果我取消选中它,则该值设置为false,如果我选中它,则更改为true,但初始checked 值为空.. 2)不显示最小长度和最大长度验证消息(参考上面的解决方案最后一条评论)..
    • 关于检查不使用 [checked] 如果您看到 stackblitz,您会看到该值为“”(起初)- 如果是复选框,则可以避免在创建控件时给出值 false -,勾选复选框时为真或假
    【解决方案2】:

    @Many,当你有数组类型时,你必须在推送数组之前创建孩子。

    ...
    } else if (element.elementType === 'array') {
        let children:any[]=[]; //declare children
        //each children of element fill our array children
        element.children.forEach(e=>{
           if (e.elementType === 'textbox') {
             children.push(new TextboxQuestion(e));
           }
        })
        //Hacemos un push not of element else element + the property children
        //changed (it will be the array created)
        questions.push(new ArrayQuestion({...element,children:children}));
    }
    

    【讨论】:

    • 谢谢@Eliseo,请提供stackblitz ..它的错误是Error: Cannot read property 'push' of undefined
    • :glups: is let children:any[]=[] //
    • 嗨 Eliseo,我在动态表单中添加了复选框,它没有给出我在选项​​中给出的值,而是将布尔值显示为 true 或 false,如果分别选中或取消选中。 . 请帮助我在使用复选框时获取我们在选项中给出的值.. 带有复选框链接的动态表单stackblitz.com/edit/angular-x4a5b6-sspsyx
    • 检查或收音机?如果你有选项必须是 NOT
    • 那我应该怎么做动态形式的复选框?在这里,我将有一个复选框,如果用户选中,则需要显示选中的值。这里我只有复选框而不是单选按钮..
    猜你喜欢
    • 2019-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 2015-03-25
    • 2018-12-19
    • 2019-06-17
    相关资源
    最近更新 更多