Reputation: 1398
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!
Upvotes: 0
Views: 525
Reputation: 73367
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 :)
Upvotes: 1