反应形式重复代码

时间:2018-01-31 13:41:42

标签: angular forms angular-material2 reactive

我正在使用被动表单,我有两种表单登录和注册。 注册:

<div class="registration_wrap">
   <div class="registration">
      <form [formGroup]="form"
            novalidate>

         <h2>Registration</h2>

         <mat-form-field class="example-full-width">
            <input matInput
                   placeholder="Username"
                   name="username"
                   [formControlName]="'username'">

            <mat-error *ngIf="form.controls['username'].invalid">{{ 
       getErrorMessage('username') }}</mat-error>
         </mat-form-field>

         <mat-form-field class="example-full-width">
            <input matInput
                   placeholder="Email"
                   name="email"
                   [formControlName]="'email'">
            <mat-error *ngIf="form.controls['email'].invalid">{{ 
        getErrorMessage('email') }}</mat-error>
         </mat-form-field>

         <mat-form-field class="example-full-width">
            <input matInput
                   placeholder="Enter your password"
                   [type]="hide ? 'password' : 'text'"
                   name="password"
                   [formControlName]="'password'">
            <mat-icon matSuffix
                      (click)="hide = !hide"
                      class="eye">
               {{hide ? 'visibility' : 'visibility_off'}}
            </mat-icon>
            <mat-error *ngIf="form.controls['password'].invalid">{{ 
      getErrorMessage('password') }}</mat-error>
         </mat-form-field>

         <ng2-password-strength-bar
                 [passwordToCheck]="form.controls['password'].value"
                 [barLabel]="barLabel"
                 [barColors]="myColors">
         </ng2-password-strength-bar>

         <mat-form-field class="example-full-width">
            <input matInput
                   placeholder="Duplicate password"
                   [type]="hide1 ? 'password' : 'text'"
                   name="duplicate"
                   [formControlName]="'duplicate'">
            <mat-icon matSuffix
                      (click)="hide1 = !hide1"
                      class="eye">
               {{hide1 ? 'visibility' : 'visibility_off'}}
            </mat-icon>
            <mat-error *ngIf="form.controls['duplicate'].invalid">{{ 
    getErrorMessage('duplicate') }}</mat-error>
         </mat-form-field>

         <mat-checkbox
                 [formControlName]="'checkbox'"
         >Check me!
         </mat-checkbox>

         <div class="but_wrap">
            <button mat-fab color="primary"
                    (click)="onSubmit(form)"
                    [disabled]="form.invalid">
               <mat-icon>done</mat-icon>
            </button>
            <button mat-fab color="accent"
                    [routerLink]="'/login'">
               <mat-icon>reply</mat-icon>
            </button>
         </div>
         <!--<p>Form value: {{ form.value | json }}</p>-->
         <!--<p>Form status: {{ form.status | json }}</p>-->
      </form>
   </div>
</div>

登录:

 <div class="login_wrap">
  <div class="login">
    <form [formGroup]="form"
          novalidate>

      <h2>Login</h2>

      <mat-form-field class="example-full-width">
        <input matInput
               placeholder="Username"
               name="username"
               [formControlName]="'username'">
        <mat-error *ngIf="form.controls['username'].invalid">{{ 
    getErrorMessage('username') }}</mat-error>
      </mat-form-field>

      <mat-form-field class="example-full-width">
        <input matInput
               placeholder="Enter your password"
               [type]="hide ? 'password' : 'text'"
               name="password"
               [formControlName]="'password'">
        <mat-icon matSuffix
                  (click)="hide = !hide"
                  class="eye">
          {{hide ? 'visibility' : 'visibility_off'}}
        </mat-icon>
        <mat-error *ngIf="form.controls['password'].invalid">{{ 
    getErrorMessage('password') }}</mat-error>
      </mat-form-field>

      <div class="but_wrap">
        <button mat-fab color="primary"
                (click)="onSubmit(form)"
                [disabled]="form.invalid">
          <mat-icon>keyboard_backspace</mat-icon>
        </button>

        <button mat-fab color="accent"
                [routerLink]="'/registration'">
          <mat-icon>group</mat-icon>
        </button>
      </div>

      <!--<p>Form value: {{ form.value | json }}</p>-->
      <!--<p>Form status: {{ form.status | json }}</p>-->
    </form>
  </div>
</div>

正如您所看到的,两个表单都有重复的代码

<mat-form-field class="example-full-width">
        <input matInput
               placeholder="Username"
               name="username"
               [formControlName]="'username'">

        <mat-error *ngIf="form.controls['username'].invalid">{{ 
    getErrorMessage('username') }}</mat-error>
     </mat-form-field>

我想知道我可以使用组件或其他我可以放置此代码并将其返回到我的HTML模板中的东西。我知道我可以用简单的组件做到这一点,但我使用反应形式。或者我应该保持原样?谢谢!

1 个答案:

答案 0 :(得分:1)

If you have exactly same fields, it can be very easily achieved with a child component, let's say child-component. And if you have same fields, I would certainly recommend to use a separate component, after all, we all want to be as DRY as possible, right? :)

So create a child component, you add that tag in your parent template and pass a nested group (or the whole form) to that child component, treat it no different as a form that would be in a single component.

Sample...

Parent TS:

myForm: FormGroup;

constructor(private fb: FormBuilder) {
  this.myForm = fb.group({ 
    someField: [''],
    nestedGroup: fb.group({
      someOtherField: ['']
    });
  })
}

Parent html:

<form [formGroup]="myForm">
  <input formControlName="someField" >
  <child-component [nestedGroup]="myForm.controls.nestedGroup"></child-component>
</form>

Then just use @Input in your child to catch the nested group, mark it as a formgroup and insert your fields with form controls inside that form group.

TS:

@Input() nestedGroup: FormGroup;

Html:

<div [formGroup]="nestedGroup">
  <input formControlName="someOtherField">
</div>

And since this the formgroup is an object and objects are mutable in JS, no need to use @Output, your parent will beware of what is going on in the child :)