步骤向导表单

Posted

技术标签:

【中文标题】步骤向导表单【英文标题】:Step wizard form 【发布时间】:2019-04-18 03:33:02 【问题描述】:

我正在使用角度动态形式制作角度应用程序,我需要将表单分成两部分。

我在第一页输入字段firstname and lastname,然后单击下一步按钮,需要加载具有email and dropdown 的子项..

HTML:

    <form (ngSubmit)="onSubmit()" [formGroup]="form">

        <div *ngFor="let question of questions" class="form-row">
            <ng-container *ngIf="question.children">
                <div [formArrayName]="question.key">
                    <div *ngFor="let item of form.get(question.key).controls; let i=index" [formGroupName]="i">
                        <div *ngFor="let item of question.children">
                            <app-question [question]="item" [form]="form.get(question.key).at(i)"></app-question>
                        </div>
                    </div>
                </div>
            </ng-container>
            <ng-container *ngIf="!question.children">
                <app-question [question]="question" [form]="form"></app-question>

            </ng-container>
        </div>

  <button (click)="goBack()"> Previous </button> &nbsp;
  <button (click)="addControls('myArray')"> Next </button> 

        <div class="form-row">
            <button type="submit" [disabled]="!form.valid">Save</button>
    </div>
  </form>

Ts:

  @Input() questions: QuestionBase<any>[] = [];
  form: FormGroup;
  payLoad = '';

  page: number = 0

  constructor(private qcs: QuestionControlService)  

  ngOnInit() 
    this.form = this.qcs.toFormGroup(this.questions);
  

  onSubmit() 
    this.payLoad = JSON.stringify(this.form.value);
  
  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))
  
  removeControls(control: string)
    let array=this.form.get(control) as FormArray;
    array.removeAt(array.length-1);
  

  goBack() 
    //Function to move to previous step
  

工作演示

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

在这个带有代码的演示中,您可以在每次点击添加按钮时看到子项(数组)被附加到同一页面的下方。

我也有 removeControl 功能,

  removeControls(control: string)
    let array=this.form.get(control) as FormArray;
    array.removeAt(array.length-1);
  

要明确,我现在不会使用它,也不会在任何地方删除任何东西.. 唯一的事情是通过addControl 功能单击下一个孩子,将孩子添加到下一页,然后在上一个返回到上一个一步。

为了附加到演示中给出的同一页面,它应该移动到下一页并再次单击上一个它应该在每次下一次单击时回到原始状态它应该给出一个新的email and dropdown 并且在上一个返回到上一步..

它应该像滑块一样移动,并在前后移动时具有滑动效果..

一切都需要纯 angular 和基于 javascript/typescript 的内容,并且没有 没有 jquery.. 正如您在我的演示中看到的那样,我没有包含任何库或 jquery..

请帮助我实现结果..卡了很长时间..

【问题讨论】:

【参考方案1】:

如果您想创建步进表单,您可以投影表单并使用表单控件连接父表单组。

ParentComponent.ts


下一个
<div class="step container" *ngIf="form.valid && nextForm" >
 <form [formGroup]="step2">
  <app-step2 (control)="enableSave($event)"></app-step2>
  <button class="btn btn-primary"  (click)="moveToPrevious()" >Previous</button>
</form>
</div>
<hr>
<button
[disabled]="eSave"
 class="btn btn-primary" (click)="save()">Save</button>
</app-stepper-wrapper>

ParentComponent.ts

name = 'Angular';
  eSave = true;
  form = new FormGroup();
  step2 = new FormGroup();
  nextForm = false;

  ngOnInit() 
    this.form.statusChanges.subscribe(s => this.eSave = true);
     
  moveToNext() 
    if (this.form.valid) 
      this.nextForm = true;
    
     
  moveToPrevious() 
    this.nextForm = false;
  
  save() 
    console.log(this.form);
    console.log(this.step2);
  
  enableSave($event) 
    if ($event == 'VALID' && this.form.valid) 

      this.eSave = false;
    
  

例如:https://stackblitz.com/edit/angular-nynvvr

【讨论】:

Chellappan,我在您的解决方案中单击下一步按钮时找不到任何内容.. Chellappan,你能帮帮我吗,过去两天卡住了,***.com/questions/53316581/… 稍后我会尽力提供帮助 兄弟小帮助..如何在反应式表单中放置标签而不是输入框?在这里stackblitz.com/edit/angular-zjoyaa?file=src/app/… 你可以看到每个template name 都是作为输入框生成的,但是我需要将其保留为标题,并且在每个标题下都会有子框。如何将模板名称输入框更改为标题?它还需要根据所选模板处于动态状态.. 我会检查兄弟!【参考方案2】:

在 goBack 方法中传递要删除的数组

   <button (click)="goBack('myArray')"> Previous </button> &nbsp;    

把这个方法放到组件ts文件中

  goBack(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).removeAt(children.length-1)

  

【讨论】:

我需要孩子们在下一页而不是在同一页..【参考方案3】:

已尝试达到您的要求:UI 部分除外。我希望你能按照你的要求处理你的 UI。

TS:

    import  Component, Input, OnInit  from '@angular/core';
    import  FormGroup, FormArray  from '@angular/forms';

    import  QuestionBase  from './question-base';
    import  QuestionControlService  from './question-control.service';

    @Component(
      selector: 'app-dynamic-form',
      templateUrl: './dynamic-form.component.html',
      providers: [QuestionControlService]
    )
    export class DynamicFormComponent implements OnInit 

      @Input() questions: QuestionBase<any>[] = [];
      form: FormGroup;
      payLoad = '';

      page: number = 0;

      constructor(private qcs: QuestionControlService)  

      ngOnInit() 
        this.form = this.qcs.toFormGroup(this.questions);
      

      onSubmit() 
        this.payLoad = JSON.stringify(this.form.value);
      
      addControls(control: string, index: any) 
        let array = this.form.get('myArray') as FormArray;
        if (array.length > this.page) 
          this.page = this.page + 1;
         else 
          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.page = this.page + 1;
        
      
      removeControls(control: string) 
        let array = this.form.get(control) as FormArray;
        array.removeAt(array.length - 1);
      

      goBack() 
        if (this.page > 0) 
          this.page = this.page - 1;
        
        //let array = this.form.get('myArray') as FormArray;
        //array.removeAt(array.length - 1);
        //Function to move to previous step
      

    

HTML : 

<div>
    <form (ngSubmit)="onSubmit()" [formGroup]="form">

        <div *ngFor="let question of questions" class="form-row">
            <ng-container *ngIf="question.children">
                <div [formArrayName]="question.key">
                    <div *ngFor="let item of form.get(question.key).controls; let i=index" [formGroupName]="i">
            <ng-template [ngIf]="i + 1 == page"> 
              <div *ngFor="let item of question.children">
                <app-question [question]="item" [form]="form.get(question.key).at(i)"></app-question>
              </div>
            </ng-template>
                    </div>
                </div>
            </ng-container>
            <ng-container *ngIf="!question.children">
                <app-question [question]="question" [form]="form"></app-question>

            </ng-container>
        </div>

  <button (click)="goBack()"> Previous </button> &nbsp;
  <button (click)="addControls('myArray',i)"> Next </button> 

        <div class="form-row">
            <button type="submit" [disabled]="!form.valid">Save</button>
    </div>
  </form> <br>

  <pre>
form?.value|json
</pre>
</div>

这将帮助您一次显示一页。如果不存在下一个表单,它将创建一个新表单。点击上一个,它会导航到旧表单。

【讨论】:

我在下一个视图中需要孩子,而不是在同一视图中。如果它移动到下一个视图,则提供 stackblitz 移动到下一个【参考方案4】:

所以,您想从form group array 中删除最后添加的控件email and dropdown

我已将代码添加到goBack() 函数中以删除子表单组控件。

组件:

  goBack() 
    //Function to move to previous step
    if(this.form.controls['myArray'])      
      const arr = <FormArray>this.form.controls.myArray;
      arr.removeAt(arr.length - 1);
    
  

工作演示:https://angular-x4a5b6-cc4kyr.stackblitz.io

【讨论】:

为此我已经有了 removeControl 功能,您可以在示例中看到.. 事情是点击下一步按钮,first name and last name 需要隐藏,电子邮件和下拉菜单需要来.. On点击上一个按钮firstname and lastname来..这只是我的要求..现在不需要删除功能..每次下一个点击dropdown and email需要在下一个屏幕中显示..问题主要是处理不同视图中的东西而不是同一页面上的东西.. 好的,我建议你在这种情况下为电子邮件和下拉菜单创建一个新路由。因为如果您手动隐藏和显示,事情就会变得复杂。

以上是关于步骤向导表单的主要内容,如果未能解决你的问题,请参考以下文章

Django:在表单向导中为步骤动态设置表单集

引导表单向导 - 在验证步骤之前阻止进度

转到表单向导中的特定步骤

django 向导,在同一步骤中使用表单和表单集

如何显示作为最终 django 表单向导步骤输入的所有数据的预览?

如何在 ReactJs 中制作步骤向导表单?