Формуляр на стойностите на елементи като JSON, използвайки ъглова форма

Създавам приложение angular 6, където използвам динамична форма Angular

Тук направих вложени полета за въвеждане, в които ще има две текстови полета за въвеждане в началния етап и при щракване върху бутона за добавяне следващите две полета за въвеждане ще се добавят при всяко щракване върху бутона за добавяне.

Тук всичко работи добре по отношение на него..

Тук използвах стойностите в 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

Същият сценарий, който се случва в stacblitz връзка без json, трябва да се случи, докато се зарежда JSON..

Дадох следното вътре 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);
  }
}

За нормално текстово поле работи, но докато за децата не работи при щракване върху бутона за добавяне (текстовите полета не се показват), дъщерните текстови полета не се добавят.

Моля, помогнете ми да постигна същия резултат, който се случва в връзка 1 също трябва да се случи, докато използване на JSON в връзка 2 .. И също така любезно не включвайте никакви библиотеки на трети страни във всичко отива в ядрото ъглово.


person Maniraj Murugan    schedule 02.11.2018    source източник


Отговори (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}));
}
person Eliseo    schedule 02.11.2018
comment
Благодаря ти, @Eliseo, любезно предоставете stackblitz, моля.. Извежда грешката като Error: Cannot read property 'push' of undefined - person Maniraj Murugan; 02.11.2018
comment
:glups: е нека children:any[]=[] //‹-необходимо е да декларирате променливата като празен масив. просто коригирано в кода - person Eliseo; 02.11.2018
comment
Здравей Eliseo, добавих квадратче за отметка в динамичния формуляр, то не дава стойността, която съм дал вътре в опциите, а по-скоро показва булевата стойност като true или false, ако поставите отметка или премахнете отметката съответно.. Моля, помогнете ми да получа стойността ние даваме опции, докато използваме квадратчето за отметка .. Динамичен формуляр с връзка към квадратчето за отметка stackblitz.com/edit/angular- x4a5b6-sspsyx - person Maniraj Murugan; 07.11.2018
comment
проверено или радио? ако имате опции, трябва да бъде‹ input type=radio ...› НЕ ‹ input type=checked› - person Eliseo; 07.11.2018
comment
Тогава как трябва да направя за квадратчето за отметка в динамична форма?? Тук ще има квадратче за отметка, където, ако потребителят отметне, стойността на отметнато трябва да се покаже. Тук имам само квадратче за отметка, а не бутон за избор.. - person Maniraj Murugan; 08.11.2018
comment
@Мани, внимавай, пропускам да покажа етикета, провери коригираните отговори - person Eliseo; 08.11.2018
comment
Относно етикета, как мога да генерирам различно име на етикет за всяко щракване върху бутон, защото ако щракна върху което и да е поле за въвеждане, тогава само първото property_one се фокусира, тъй като [id]="property_one" и <label [attr.for]="proprty_one"> бяха еднакви за всеки добавен ред към бутона за щракване.. - person Maniraj Murugan; 08.11.2018
comment
можете да замените всички question.key с index?question.key+index:question.key и да създадете Input() индекс - промених stackblitz, за да добавя това модификация- - person Eliseo; 08.11.2018
comment
Благодаря, @Eliseo.. Що се отнася до етикета, сега съм ясен.. Но при валидирането имам съмнение.. Тук съм дал само необходимото съобщение за показване, ако !isValid, но трябва да покажа minlength и maxlength съобщение отделно.. Как мога ли да го направя?? - person Maniraj Murugan; 08.11.2018
comment
Опитах с, <div *ngIf="question.key.invalid && (question.key.dirty || question.key.touched)" class="text-danger"> <div class="input-error-msg" *ngIf="question.key.errors?.required">{{question.label}} is required</div> <div class="input-error-msg" *ngIf="question.key.errors?.minlength"> Minimum {{question.minlength}} is required</div> </div> Но нищо не се случи.. - person Maniraj Murugan; 08.11.2018
comment
Stackblitz с атрибути minlength и maxlength, stackblitz.com/edit/angular-x4a5b6-bdtqch - person Maniraj Murugan; 08.11.2018
comment
Ако погледнете тук, любезно вижте и коментара за решението по-долу.. Получавам добра помощ от вас относно динамичната форма.. Моля, помогнете ми да го поправя.. - person Maniraj Murugan; 08.11.2018
comment
Актуализирам втория си отговор (и връзката към stackblitz), опитайте се да добавите условията за добавяне на валидаторите min и max) - person Eliseo; 08.11.2018
comment
Моля, проверете втория отговор stackblitz дали е актуализиран, защото не можах да видя никакви промени в него относно валидирането.. - person Maniraj Murugan; 09.11.2018
comment
Здравей Eliseo, Ето още един нов въпрос за теб stackoverflow.com/questions/53220425/ за корекция на данни към тези елементи на формуляр по време на редактиране. Тъй като вие сами знаете пътя, по който вървя в тази ъглова динамична форма, не можах да получа добра помощ от други .. Надявам се, че разбирате въпроса за редактиране на данните и следователно можете да ми помогнете за същото.. - person Maniraj Murugan; 09.11.2018
comment
Eliseo, ето още един въпрос към вас в нашата динамична форма, stackoverflow.com/questions/53261208/ - person Maniraj Murugan; 12.11.2018

Трябва да добавите нов тип "кутия за отметка"

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

Актуализация ако искаме да добавим още валидатори, погледнете функцията „toFormGroup“ на question.service.ts

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

Вижте разклонения stackblitz

person Eliseo    schedule 08.11.2018
comment
Защо връща булева стойност вместо низа, който е даден като стойност в JSON? Квадратчето за отметка може да бъде няколко квадратчета за отметка, но като цяло ще върне само стойност know?? w3schools.com/tags/tryit.asp?filename=tryhtml_input_checked - person Maniraj Murugan; 08.11.2018
comment
любезно ми помогнете в тези два сценария 1) Въпреки че използвам квадратчето за отметка, което връща булево или вярно, или невярно, в началния етап дадох [checked]="true", но не можах да видя стойността като true за property_check, но квадратчето за отметка е отметнато.. Като има предвид, че ако премахна отметката, тогава стойността се задава на false и ако я проверя, тогава се променя на true, но при първоначалната checked стойността е празна.. 2) Съобщението за валидиране на минимална и максимална дължина не се показва (вижте последния коментар на решението по-горе). - person Maniraj Murugan; 08.11.2018
comment
Относно проверките НЕ използвайте [проверено], ако видите stackblitz, виждате, че стойността е (първоначално)- можете да избегнете, когато създавате контролата, да дадете стойност false, ако е квадратче за отметка-, и true или false, когато поставите отметка отметка - person Eliseo; 08.11.2018