如何在 Angular 中使用嵌套表单并在 Mongodb 中保存数据

How to use nested Forms in Angular and save data in Mongodb

我正在尝试保存数据,我拖放到 Mongodb 中的一个部分,但是当我使用嵌套表单时出现此错误:

Error: Cannot find control with name: 'elementen'

我从这个网站得到了例子:LogRocket, 这就是我所做的,(顺便说一句,这不是整个代码,只是一个片段,所以可能会遗漏一些 div):

formadd.component.tsformadd.component.html

export class FormaddComponent implements OnInit {
  //paginaForm: FormGroup;

  paginaForm = new FormGroup({
    form_name: new FormControl(''),
    elementen: new FormGroup({
      textbox: new FormControl(''),
      email: new FormControl(''),
      phone: new FormControl(''),
      number: new FormControl(''),
      date: new FormControl(''),
      datetime: new FormControl(''),
      textarea: new FormControl(''),
      checkbox: new FormControl(''),
      radio: new FormControl(''),
      autocomplete: new FormControl(''),
      file: new FormControl(''),
    })
  });

  constructor(private fb: FormBuilder, private bs: FoldersService, private http: HttpClient) {
    this.createForm();
  }

  createForm(){
    this.paginaForm = this.fb.group({
      form_name: ['', Validators.required],
      textbox: ['', Validators.required],
      email: ['', Validators.required],
      phone: ['', Validators.required],
      number: ['', Validators.required],
      date: ['', Validators.required],
      datetime: ['', Validators.required],
      textarea: ['', Validators.required],
      checkbox: ['', Validators.required],
      radio: ['', Validators.required],
      autocomplete: ['', Validators.required],
      file: ['', Validators.required]
    });
  }
   onFormSubmit() {
    alert(JSON.stringify(this.paginaForm.value));
  }

  addFolders(form_name, textbox, email, phone, number, date, datetime, textarea, checkbox, radio, autocomplete, file) {
    this.bs.addFolders(form_name, textbox, email, phone, number, date, datetime, textarea,checkbox, radio, autocomplete, file);
  }

  addPagina() {
    (<FormArray>this.paginaForm.get('forms')).push(this.fb.group({
      form_name: ['', Validators.required],
      textbox: [],
      email: [],
      phone: [],
      number: [],
      date: [],
      datetime: [],
      textarea: [],
      checkbox: [],
      radio: [],
      autocomplete: [],
      file: [],
    }));
  }

  get forms() {
    return (<FormArray>this.paginaForm.get('forms')).controls;
  }

  removePagina(i: number) {
    (<FormArray>this.paginaForm.get('forms')).removeAt(i);
  }
  }
<div class="row" id="formulier">
      <div class="col-md-9" id="add">
        <div class="add">
        <div class="container-fluid">
          <form [formGroup]="paginaForm" (submit)="onFormSubmit()">
            <div class="geheel">
              <div class="row" id="geheel-element">
                <div class="col-md-12">
                  <div class="title">
                    <mat-toolbar class="toolbar" color="warn">
                      <h2 class="pagina-naam"><input class="form-control" placeholder="Formulier Naam" type="text"
                          formControlName="form_name" #form_name /></h2>
                    </mat-toolbar>
                  </div>
                </div>
                <div class="col-md-12">
                  <div formGroupName="elementen">
                  <div class="element">
                    <!--a dropzone-->
                    <!--to allow dropping content that is not [dndDraggable] set dndAllowExternal to true-->
                    <section class="voeg-element" placeholder="voeg element toe" dndDropzone
                      (dndDragover)="onDragover($event)" (dndDrop)="onDrop($event,model.attributes)" class="dndDropArea"
                      [ngClass]="{'empty':model.attributes.length == 0}" [style.backgroundColor]="model.theme.bgColor"
                      [style.color]="model.theme.textColor">

                      <div class="field" *ngFor="let item of model.attributes;let i= index;"
                        (dndStart)="onDragStart($event)" (dndCanceled)="onDragCanceled($event)"
                        (dndMoved)="onDragged(item, model.attributes, 'move')" [dndEffectAllowed]="'all'"
                        [dndDraggable]="item">
                        <div class="row form-group">
                          <div class="fp"><i class="fa fa-ellipsis-v dndHandle" dndHandle></i></div>
                          <div class="col-7">
                            <!-- <i [ngClass]="item.icon" class="fa pull-left"></i>
                      <h5>{{item.label}}
                      <span *ngIf="item.required" class="red">*</span></h5> -->
                            <div *ngIf="item.type=='text'">
                              <label>{{item.label}}</label> <label *ngIf="item.required" class="text-danger">*</label>
                              <input type="text" class="form-control" id="{{item.name}}"
                                placeholder="{{item.placeholder}}" formControlName="textbox" #textbox>
                            </div>
                            <div *ngIf="item.type=='email'">
                              <label>{{item.label}}</label> <label *ngIf="item.required" class="text-danger">*</label>
                              <input type="email" class="form-control" id="{{item.name}}"
                                placeholder="{{item.placeholder}}" formControlName="email" #email>
                            </div>
                            <div *ngIf="item.type=='phone'">
                              <label>{{item.label}}</label> <label *ngIf="item.required" class="text-danger">*</label>
                              <input type="text" class="form-control" id="{{item.name}}"
                                placeholder="{{item.placeholder}}" formControlName="phone" #phone>
                            </div>
                            <div *ngIf="item.type=='number'">
                              <label>{{item.label}}</label> <label *ngIf="item.required" class="text-danger">*</label>
                              <input type="number" class="form-control" id="{{item.name}}" min="{{item.min}}"
                                max="{{item.max}}" placeholder="{{item.placeholder}}" formControlName="number" #number>
                            </div>
                            <div *ngIf="item.type=='date'">
                              <label>{{item.label}}</label> <label *ngIf="item.required" class="text-danger">*</label>
                              <input type="date" class="form-control" id="{{item.name}}"
                                placeholder="{{item.placeholder}}" formControlName="date" #date>
                            </div>
                            <div *ngIf="item.type=='datetime-local'">
                              <label>{{item.label}}</label> <label *ngIf="item.required" class="text-danger">*</label>
                              <input type="datetime-local" class="form-control" id="{{item.name}}"
                                placeholder="{{item.placeholder}}" formControlName="datetime" #datetime>
                            </div>
                            <div *ngIf="item.type=='textarea'">
                              <label>{{item.label}}</label> <label *ngIf="item.required" class="text-danger">*</label>
                              <textarea class="form-control" id="{{item.name}}" placeholder="{{item.placeholder}}" formControlName="textarea" #textarea>
                                </textarea>
                            </div>
                            <div *ngIf="item.type=='file'">
                              <label>{{item.label}} (File can't be uploaded right now)</label> <label
                                *ngIf="item.required" class="text-danger">*</label>
                              <input type="file" class="form-control" id="{{item.name}}"
                                placeholder="{{item.placeholder}}" formControlName="file" #file>
                              <small class="form-text text-danger">(File can't be uploaded right now)</small>
                            </div>
                            <div *ngIf="item.type=='autocomplete'">
                              <label>{{item.label}}</label> <label *ngIf="item.required" class="text-danger">*</label>
                              <select class="form-control" id="{{item.name}}" formControlName="autocomplete" #autocomplete>
                                <option *ngFor="let v of item.values" [value]="v.value">{{v.label}}</option>
                              </select>
                              <!-- <small class="form-text text-muted">{{item.description}}</small> -->
                            </div>
                            <div *ngIf="item.type=='checkbox'">
                              <label>{{item.label}}</label> <label *ngIf="item.required" class="text-danger">*</label>
                              <div *ngFor="let v of item.values" class="inline-form-group">
                                <label class="cust-check-bx">
                                  <input type="checkbox" [value]="v.value" name="{{item.name}}"
                                    (click)="toggleValue(v)" formControlName="checkbox" #checkbox>
                                  {{v.label}}
                                  <span class="checkmark"></span>
                                </label>
                              </div>
                            </div>
                            <div *ngIf="item.type=='radio'">
                              <label>{{item.label}}</label> <label *ngIf="item.required" class="text-danger">*</label>
                              <div *ngFor="let v of item.values" class="inline-form-group">
                                <label class="cust-check-bx">
                                  <input type="radio" [value]="v.value" name="{{item.name}}" formControlName="radio" #radio> {{v.label}}
                                  <span class="checkmark"></span>
                                </label>
                              </div>
                            </div>
                            <!-- <div *ngIf="item.type=='button'" class="btn-cont">
                              <input type="{{item.subtype}}" (click)="submit()" value="{{item.label}}"
                                class="btn btn-primary" id="{{item.name}}">
                            </div> -->
                          </div>
                          <div class="col-4">
                            <i *ngIf="item.toggle" (click)="item.toggle=false" class="fa fa-chevron-up pull-right"></i>
                            <i *ngIf="!item.toggle" (click)="item.toggle=true"
                              class="fa fa-chevron-down pull-right"></i>
                            <i (click)="removeField(i)" class="fa fa-trash pull-right"></i>
                          </div>
                        </div>
                        <div *ngIf="item.toggle" class="toggle-Wrapper">
                          <div class="form-group">
                            <label>Required</label>
                            <i *ngIf="item.required" (click)="item.required=false" class="fa fa-toggle-on red"></i>
                            <i *ngIf="!item.required" (click)="item.required=true" class="fa fa-toggle-off"></i>
                            <span class="pull-right ucfirst">{{item.type}}</span>
                          </div>
                          <div class="form-group">
                            <label>Label</label>
                            <input class="form-control" type="text" [(ngModel)]="item.label" />
                          </div>
                          <div class="form-group">
                            <label>Name</label>
                            <input class="form-control" type="text" [(ngModel)]="item.name" />
                          </div>
                          <div class="form-group">
                            <label>Placeholder</label>
                            <input class="form-control" type="text" [(ngModel)]="item.placeholder" />
                          </div>
                          <div class="form-group">
                            <label>Regex</label>
                            <input class="form-control" type="text" [(ngModel)]="item.regex" />
                          </div>
                          <div *ngIf="item.regex" class="form-group">
                            <label>Error text</label>
                            <input class="form-control" type="text" [(ngModel)]="item.errorText" />
                          </div>

                          <!-- number -->
                          <div *ngIf="item.type=='number'" class="row">
                            <div class="col-6">
                              <div class="form-group">
                                <label>Min</label>
                                <input class="form-control" type="text" [(ngModel)]="item.min" />
                              </div>
                            </div>
                            <div class="col-6">
                              <div class="form-group">
                                <label>Max</label>
                                <input class="form-control" type="text" [(ngModel)]="item.max" />
                              </div>
                            </div>
                          </div>

                          <!-- radio || checkbox || autocomplete -->
                          <div *ngIf="item.type=='radio'|| item.type=='checkbox' || item.type=='autocomplete'">
                            <div class="row">
                              <div class="col-5">
                                <div class="form-group">
                                  <label>Label</label>
                                </div>
                              </div>
                              <div class="col-5">
                                <div class="form-group">
                                  <label>Value</label>
                                </div>
                              </div>
                              <div class="col-2">
                                <div class="form-group">
                                  <label>Action</label>
                                </div>
                              </div>
                            </div>
                            <div *ngFor="let i of item.values; let valueIndex=index;" class="row">
                              <div class="col-5">
                                <div class="form-group">
                                  <input class="form-control" type="text" [(ngModel)]="i.label" />
                                </div>
                              </div>
                              <div class="col-7">
                                <div class="form-group">
                                  <input class="form-control" type="text" [(ngModel)]="i.value" />
                                </div>
                              </div>
                              <!-- <div class="col-2">
                                <div class="form-group">
                                  <label (click)="item.values.splice(valueIndex,1)">remove</label>
                                </div>
                              </div> -->
                            </div>
                            <div class="row">
                              <div class="col-5">
                                <div class="form-group">
                                  <input class="form-control" type="text" [(ngModel)]="value.label" />
                                </div>
                              </div>
                              <div class="col-7">
                                <div class="form-group">
                                  <input class="form-control" type="text" [(ngModel)]="value.value" />
                                </div>
                              </div>
                              <!-- <div class="col-2">
                                <div class="form-group">
                                  <label (click)="addValue(item.values)">Add</label>
                                </div>
                              </div> -->
                            </div>
                          </div>
                        </div>
                      </div>
                    </section>
                    <div class="row">
                    <div class="col-md-5" id="verwijder">
                      <button (click)="removePagina(i)">Verwijder Pagina</button>
                    </div>
                    <div class="col-md-5" id="opslaan">
                      <button (click)="addFolders(form_name.value, textbox?.value, email?.value, phone?.value, number?.value, date?.value, datetime?.value, textarea?.value, file?.value, autocomplete?.value, checkbox?.value, radio?.value)"
                        [disabled]="paginaForm.pristine || paginaForm?.invalid">Opslaan Pagina</button>
                    </div>
                  </div>
                  </div>
                  </div>
                </div>
              </div>
            </div>

            <div *ngIf="report" class="padding20 white-bg">
              <div class="row">
                <div class="col-12 btn-cont">
                  <button (click)="report=false" class="btn btn-primary">
                    << Back</button> </div> <div class="col-12 spacer30">
                </div>
                <!-- if records found -->
                <div *ngIf="reports?.length > 0" class="col-12">
                  <div *ngFor="let records of reports" class="report-block">
                    <div *ngFor="let record of records.attributes">
                      <div *ngIf="record.type !='button' && record.type !='paragraph'" class="row">
                        <div class="col-4">{{record.label}}</div>
                        <div class="col-8">{{record.value}}</div>
                      </div>
                    </div>
                  </div>
                  <!-- <pre>{{reports|json}}</pre> -->
                </div>
                <!-- if no records found -->
                <div *ngIf="reports?.length == 0" class="col-12 btn-cont">
                  No response found
                </div>
              </div>
            </div>
            <pre *ngIf="show==1 && model">
                  {{model|json}}
                  </pre>
            <div class="toevoegen">
              <button type="button" (click)="addPagina()">
                Pagina toevoegen
              </button>
            </div>
          </form>
          </div>
        </div>
      </div>

我真的需要帮助,如果有其他方法可以在数据库中保存可拖动对象,请告诉我。

这看起来像是您的一个小错字。在您最初定义 public 属性 paginaForm 的组件中,您创建了 formGroup elementen.

paginaForm = new FormGroup({
    form_name: new FormControl(''),
    elementen: new FormGroup({ .    <--- Notice elementen is here
      textbox: new FormControl(''),
      email: new FormControl(''),
      phone: new FormControl(''),
      number: new FormControl(''),
      date: new FormControl(''),
      datetime: new FormControl(''),
      textarea: new FormControl(''),
      checkbox: new FormControl(''),
      radio: new FormControl(''),
      autocomplete: new FormControl(''),
      file: new FormControl(''),
    })
  });

但是,然后在您的构造函数中调用 this.createForm(),如果您查看该函数,您会看到 您重新创建了没有 elementen[= 的表单17=]

createForm(){
    this.paginaForm = this.fb.group({
      form_name: ['', Validators.required],  <-- No more elementen :/
      textbox: ['', Validators.required],
      email: ['', Validators.required],
      phone: ['', Validators.required],
      number: ['', Validators.required],
      date: ['', Validators.required],
      datetime: ['', Validators.required],
      textarea: ['', Validators.required],
      checkbox: ['', Validators.required],
      radio: ['', Validators.required],
      autocomplete: ['', Validators.required],
      file: ['', Validators.required]
    });
  }

编辑:回应评论中的问题:它是一个formGroup并不重要。下面是您的组件如何正确初始化表单的示例。

export class FormaddComponent implements OnInit {
  public paginaForm: FormGroup;

  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.createForm();
  }

  private createForm(): void {
    this.paginaForm = this.fb.group({
      form_name: ['', Validators.required],
      elementen: this.fb.group({
        textbox: ['', Validators.required],
        email: ['', Validators.required],
        phone: ['', Validators.required],
        number: ['', Validators.required],
        date: ['', Validators.required],
        datetime: ['', Validators.required],
        textarea: ['', Validators.required],
        checkbox: ['', Validators.required],
        radio: ['', Validators.required],
        autocomplete: ['', Validators.required],
        file: ['', Validators.required]
      })
    });
  }
}