JSON的Angular 7动态反应式表单如何自定义对齐字段

时间:2019-12-30 07:21:18

标签: angular angular-reactive-forms

我正在使用Medium Article的引用在Angular 7中开发动态的Reactive表单,我能够创建表单,但是无法自定义对齐字段,所有表单字段均位于每个字段下方其他,我希望它们位于每个字段旁边,因为我们将两个字段放在同一标签中以实现模板驱动形式。enter image description here

我的dynamic-form.component.ts文件

@Component({
  exportAs: "dynamicForm",
  selector: "dynamic-form",
  template: `
  <form class="dynamic-form" [formGroup]="form" (submit)="onSubmit($event)">
  <ng-container *ngFor="let field of fields;" dynamicField [field]="field" [group]="form">
  </ng-container>
  </form>
  `,
  styles: []
})
export class DynamicFormComponent implements OnInit {
  @Input() fields: FieldConfig[] = [];

  @Output() submit: EventEmitter<any> = new EventEmitter<any>();

  form: FormGroup;

  get value() {
    return this.form.value;
  }
  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.form = this.createControl();
  }

  onSubmit(event: Event) {
    event.preventDefault();
    event.stopPropagation();
    if (this.form.valid) {
      this.submit.emit(this.form.value);
    } else {
      this.validateAllFormFields(this.form);
    }
  }

  createControl() {
    const group = this.fb.group({});
    this.fields.forEach(field => {
      if (field.type === "button") return;
      const control = this.fb.control(
        field.value,
        this.bindValidations(field.validations || [])
      );
      group.addControl(field.name, control);
    });
    return group;
  }

  bindValidations(validations: any) {
    if (validations.length > 0) {
      const validList = [];
      validations.forEach(valid => {
        validList.push(valid.validator);
      });
      return Validators.compose(validList);
    }
    return null;
  }

  validateAllFormFields(formGroup: FormGroup) {
    Object.keys(formGroup.controls).forEach(field => {
      const control = formGroup.get(field);
      control.markAsTouched({ onlySelf: true });
    });
  }
}

app.component.ts文件

import { Component, ViewChild } from "@angular/core";
import { Validators } from "@angular/forms";
import { FieldConfig } from "./field.interface";
import { DynamicFormComponent } from "./components/dynamic-form/dynamic-form.component";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  @ViewChild(DynamicFormComponent) form: DynamicFormComponent;
  regConfig: FieldConfig[] = [
    {
      type: "input",
      label: "First Name",
      inputType: "text",
      name: "name",
      validations: [
        {
          name: "required",
          validator: Validators.required,
          message: "Name Required"
        },
        {
          name: "pattern",
          validator: Validators.pattern("^[a-zA-Z]+$"),
          message: "Accept only text"
        }
      ]
    },
    {
      type: "input",
      label: "Last Name",
      inputType: "text",
      name: "lastname",
      validations: [
        {
          name: "required",
          validator: Validators.required,
          message: "Last Name Required"
        },
        {
          name: "pattern",
          validator: Validators.pattern("^[a-zA-Z]+$"),
          message: "Accept only text"
        }
      ]
    },
    {
      type: "input",
      label: "Email Address",
      inputType: "email",
      name: "email",
      validations: [
        {
          name: "required",
          validator: Validators.required,
          message: "Email Required"
        },
        {
          name: "pattern",
          validator: Validators.pattern(
            "^[a-z0-9._%+-]+@[a-z0-9.-]+.[a-z]{2,4}$"
          ),
          message: "Invalid email"
        }
      ]
    },


    {
      type: "select",
      label: "Country",
      name: "country",
      value: "UK",
      options: ["India", "UAE", "UK", "US"]
    },
    {
      type: "checkbox",
      label: "Accept Terms",
      name: "term",
      value: true
    },
    {
      type: "button",
      label: "Save"
    }
  ];

  submit(value: any) {}
}

app.component.html

    <div class="form">
  <div style="text-align:center">
    <h1>
     General Partner Info
    </h1>
  </div>
  <dynamic-form [fields]="regConfig" (submit)="submit($event)">
  </dynamic-form>
  <!-- <div class="margin-top">
    {{ form.value | json }}
  </div> -->
</div>

1 个答案:

答案 0 :(得分:1)

完整的工作示例,您可以在此StackBlitz Link

中找到

在这里,您需要使用display: flex ...

 .main{
   width: 100%;
   display: flex;
   flex-direction: row;
   flex-wrap: wrap;
}
.body {
   width: 40%;
   margin: 10px;
}
.content{
   display: flex;
   justify-content: space-between;
}

在以上CSS中,flex-direction: rowflex-wrap: wrap将其分解为新行非常有用。

您的模板是...

<div class="container">
   <div class="main">
       <div  class="body" *ngFor ="let control of regConfig ; let i = index; let odd=odd; let even=even;" >
          <div class="content" [ngSwitch]="control.type">
           <ng-template ngSwitchCase="input">
             <label> {{ control.label }} </label>
             <input type="text" placeholder="text">
           </ng-template>
           <ng-template ngSwitchCase="select">
              <label> {{ control.label }} </label>
              <select>
                <option> default </option>
              </select>
           </ng-template>
           <ng-template ngSwitchCase="checkbox">
              <label> {{ control.label }} </label>
              <input type="checkbox" >
           </ng-template>
           <ng-template ngSwitchCase="button">
              <button> {{control.label}} </button>
           </ng-template>
       </div>
    </div>
  </div>
</div>

更新:1

如果必须使用引导程序类,则可以将bootstrap-grid系统用于不同大小的断点。

<div class="container">
     <div class="row">
          <div  class=" col-12 col-sm-6" *ngFor ="let control of regConfig ; let i = index; let odd=odd; let even=even;" >
               <div class="col-xs-6 col-12 " [ngSwitch]="control.type">
                  <ng-template ngSwitchCase="input">
                      <label> {{ control.label }} </label>
                      <input class="form-control"  type="text" placeholder="text">
                  </ng-template>
                  <ng-template ngSwitchCase="select">
                      <label> {{ control.label }} </label>
                      <select class="form-control">
                         <option> default </option>
                      </select>
                  </ng-template>
                  <ng-template ngSwitchCase="checkbox">
                     <div class = "form-check ">
                       <input class="form-check-input" [id]="control.name" type="checkbox" >
                       <label class="form-check-label" [for]="control.name"> {{ control.label }} </label>
                     </div>
                  </ng-template>
                  <ng-template ngSwitchCase="button">
                     <div class="form-group mt-2">
                         <button class="btn btn-primary"> {{control.label}}</button>
                     </div>
                  </ng-template>
               </div>
           </div>
      </div>
</div>