0

I'm using reactive form and I have two forms login and registration. Registration:

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

Login:

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

As you can see both forms have duplicate code

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

And I want to know can I use component or something where I can put this code and return it in my HTML template. I know I can do that with simple component, but I use reactive forms. Or I should leave it as it is? Thank you!

1 Answer 1

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 :)

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.