I have created common input field which can be usable across app and it will work with or without reactive form.
For e.g.: I have created common input angular component but it works with reactive form only as it has formGroup and formControlName.
input.html:
<div *ngIf="isRequired" [formGroup]="parentForm">
<label >
{{labelText}}
</label>
<input [type]="inputType" [control]="control" [formControlName]="formControlNameText" [placeholder]="placeholderText">
</div>
input.ts:
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'app-input',
templateUrl: './input.component.html',
styleUrls: ['./input.component.scss'],
})
export class InputComponent implements OnInit {
@Input() parentForm: any;
@Input() labelText: string;
@Input() inputType: string = "text";
@Input() formControlNameText: string;
@Input() placeholderText: string;
@Input() isRequired: boolean = false;
@Input() requiredMsg: string;
@Input() maxlengthMsg: string;
@Input() control: any;
@Input() type: string;
constructor() { }
ngOnInit() { }
}
Call from one of my form Page:
<app-input parentForm="surveyResponseForm" labelText="test" inputType="text" placeholderText="placeholder"
formControlNameText="authorName" control="" isRequired=true id="authorName">
</app-input>
How do I use this common input if I want to use this without form?
I mean how do I use this selector: app-input
in a component which doesn't have any form.
CodePudding user response:
You could add an @Input() property to your component, for example useInForm: boolean, and check its value in your template. If useInForm is true, you would use the [formGroup] and formControlName properties, otherwise you would use a regular element without those properties example in the withoutFormTemplate.
<div *ngIf="isRequired && useInForm; else withoutFormTemplate" [formGroup]="parentForm">
<label >
{{labelText}}
</label>
<input [type]="inputType" [control]="control" [formControlName]="formControlNameText" [placeholder]="placeholderText">
</div>
<ng-template #withoutFormTemplate>
<input [(ngModel)]="control" [type]="inputType" [placeholder]="placeholderText">
<ng-template>
CodePudding user response:
You solve it by creating a FormGroup. It's not easiest solution, but that working on multiple scenarios. Or maybe give you some clues how to solve your problem...
Form component ts
// Reactive Forms
form: FormGroup;
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
// Form structure and validators
this.form = this.formBuilder.group({
'user' : this.formBuilder.group({
'username' : ['', Validators.required],
'email' : ['', [Validators.required, Validators.email]]
}),
'identity' : this.formBuilder.group({
'firstname' : ['', Validators.required],
'lastname' : ['', Validators.required],
'address' : this.formBuilder.group({
'street' : ['', Validators.required],
'city' : ['', Validators.required],
})
})
});
}
onSubmit() {
// Get object with same structure as form but only with values
console.log(this.form.value);
alert('Form is ' (this.form.invalid ? 'invalid' : 'valid'));
}
Form component html
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<form-text [formGroupParent]="form.get(['user'])"
[formGroupControlName]="'username'">
</form-text>
<form-text [formGroupParent]="form.get(['user'])"
[formGroupControlName]="'email'">
</form-text>
<hr>
<form-text [formGroupParent]="form.get(['identity'])"
[formGroupControlName]="'firstname'">
</form-text>
<form-text [formGroupParent]="form.get(['identity'])"
[formGroupControlName]="'lastname'">
</form-text>
<hr>
<form-text [formGroupParent]="form.get(['identity','address'])"
[formGroupControlName]="'street'">
</form-text>
<form-text [formGroupParent]="form.get(['identity','address'])"
[formGroupControlName]="'city'">
</form-text>
<button type="submit">Submit</button>
</form>
Custom input component ts (form-text)
// Needed to bind formControlName
@Input() formGroupParent: FormGroup;
@Input() formGroupControlName: string;
// FormControl store validators
control: FormControl;
ngOnInit() {
// Fetch Form control (validator) from FormGroup parent
this.control = <FormControl>this.formGroupParent.get(this.formGroupControlName);
}
Custom input component html (form-text)
<ng-container [formGroup]="formGroupParent">
<label>{{formGroupControlName}}</label>
<input type="text" formControlName="{{formGroupControlName}}">
</ng-container
Blockquote