I have a reactive form that I want to show in steps. When the first field is validated, the form will show the next field. Being new to Angular the form works in some cases. The problems arise when a form field changes to a specific option. One of the issues may be the form has a few variables, the user can select (A,B), but the form has other choices that lead to other fields.
Example: if the form has a dropdown, and the user selects option (A), I only want to show the next field related to the selection. If the user selects option (B) I want to show different fields. If the user changes from A to B the form should hide fields not related to the selection. Here's an example of my code.
Thanks in Advance!
<div class="form-group">
<label class="label" for="propertyType">Property Type</label>
<select class="field" id="propertyType" formControlName="propertyType">
<option value="" disabled>Commercial or Residential?</option>
<option value="commercial">Commercial</option>
<option value="residential">Residential</option>
</select>
<div
*ngIf="
leadForm.get('propertyType')?.invalid &&
leadForm.get('propertyType')?.touched
"
>
Property type is required.
</div>
</div>
<!-- Transaction Type -->
<div class="form-group" *ngIf="leadForm.get('propertyType')?.valid">
<i class="fa-solid fa-clipboard-list" style="text-align: center"></i>
<label class="label" for="transactionType">Transaction Type</label>
<select class="field" id="transactionType" formControlName="transactionType">
<option value="" disabled selected>Purchase or Refinance?</option>
<option value="purchase">Purchase</option>
<option value="refinance">Refinance</option>
</select>
<div
*ngIf="
leadForm.get('transactionType')?.invalid &&
leadForm.get('transactionType')?.touched
"
>
Transaction type is required.
</div>
</div>
<!-- Under Contract (Purchase Only) -->
<div
class="form-group"
*ngIf="selectedType === 'purchase' && leadForm.get('transactionType')?.valid"
>
<label class="label" for="underContract">Are you under contract?</label>
<select class="field" id="underContract" formControlName="underContract">
<option value="" disabled selected>Yes or No?</option>
<option value="yes">Yes</option>
<option value="no">No</option>
</select>
<div
*ngIf="
leadForm.get('underContract')?.invalid &&
leadForm.get('underContract')?.touched
"
>
Please select if you are under contract.
</div>
</div>
<!-- Purchase Price (if under contract) -->
<div
class="form-group"
*ngIf="selectedType === 'purchase' && leadForm.get('underContract')?.valid"
>
<label class="label" for="purchasePrice">Purchase Price</label>
<input
type="text"
class="field"
id="purchasePrice"
formControlName="purchasePrice"
placeholder="Enter Purchase Price"
/>
<div
*ngIf="
leadForm.get('purchasePrice')?.invalid &&
leadForm.get('purchasePrice')?.touched
"
>
Purchase price is required.
</div>
</div>
<!-- Loan Amount -->
<div class="form-group" *ngIf="leadForm.get('purchasePrice')?.valid">
<label class="label" for="loanAmount">Loan amount requested</label>
<input
type="text"
class="field"
id="loanAmount"
formControlName="loanAmount"
placeholder="Enter loan amount"
/>
<div
*ngIf="
leadForm.get('loanAmount')?.errors?.['required'] &&
leadForm.get('loanAmount')?.touched
"
>
Loan amount is required.
</div>
<div
*ngIf="
leadForm.get('loanAmount')?.errors?.['minDigits'] &&
leadForm.get('loanAmount')?.touched
"
>
Loan amount must be at least 6 digits.
</div>
</div>
I tried using *ngIf="selectedType === 'purchase' to tell the form which field to target/show next. Also tried the same with a yes/ no option to add the correct field next. I don't which formControlName to use or even if I on the right track.
I also tried creating the steps in my TS file.
I have a reactive form that I want to show in steps. When the first field is validated, the form will show the next field. Being new to Angular the form works in some cases. The problems arise when a form field changes to a specific option. One of the issues may be the form has a few variables, the user can select (A,B), but the form has other choices that lead to other fields.
Example: if the form has a dropdown, and the user selects option (A), I only want to show the next field related to the selection. If the user selects option (B) I want to show different fields. If the user changes from A to B the form should hide fields not related to the selection. Here's an example of my code.
Thanks in Advance!
<div class="form-group">
<label class="label" for="propertyType">Property Type</label>
<select class="field" id="propertyType" formControlName="propertyType">
<option value="" disabled>Commercial or Residential?</option>
<option value="commercial">Commercial</option>
<option value="residential">Residential</option>
</select>
<div
*ngIf="
leadForm.get('propertyType')?.invalid &&
leadForm.get('propertyType')?.touched
"
>
Property type is required.
</div>
</div>
<!-- Transaction Type -->
<div class="form-group" *ngIf="leadForm.get('propertyType')?.valid">
<i class="fa-solid fa-clipboard-list" style="text-align: center"></i>
<label class="label" for="transactionType">Transaction Type</label>
<select class="field" id="transactionType" formControlName="transactionType">
<option value="" disabled selected>Purchase or Refinance?</option>
<option value="purchase">Purchase</option>
<option value="refinance">Refinance</option>
</select>
<div
*ngIf="
leadForm.get('transactionType')?.invalid &&
leadForm.get('transactionType')?.touched
"
>
Transaction type is required.
</div>
</div>
<!-- Under Contract (Purchase Only) -->
<div
class="form-group"
*ngIf="selectedType === 'purchase' && leadForm.get('transactionType')?.valid"
>
<label class="label" for="underContract">Are you under contract?</label>
<select class="field" id="underContract" formControlName="underContract">
<option value="" disabled selected>Yes or No?</option>
<option value="yes">Yes</option>
<option value="no">No</option>
</select>
<div
*ngIf="
leadForm.get('underContract')?.invalid &&
leadForm.get('underContract')?.touched
"
>
Please select if you are under contract.
</div>
</div>
<!-- Purchase Price (if under contract) -->
<div
class="form-group"
*ngIf="selectedType === 'purchase' && leadForm.get('underContract')?.valid"
>
<label class="label" for="purchasePrice">Purchase Price</label>
<input
type="text"
class="field"
id="purchasePrice"
formControlName="purchasePrice"
placeholder="Enter Purchase Price"
/>
<div
*ngIf="
leadForm.get('purchasePrice')?.invalid &&
leadForm.get('purchasePrice')?.touched
"
>
Purchase price is required.
</div>
</div>
<!-- Loan Amount -->
<div class="form-group" *ngIf="leadForm.get('purchasePrice')?.valid">
<label class="label" for="loanAmount">Loan amount requested</label>
<input
type="text"
class="field"
id="loanAmount"
formControlName="loanAmount"
placeholder="Enter loan amount"
/>
<div
*ngIf="
leadForm.get('loanAmount')?.errors?.['required'] &&
leadForm.get('loanAmount')?.touched
"
>
Loan amount is required.
</div>
<div
*ngIf="
leadForm.get('loanAmount')?.errors?.['minDigits'] &&
leadForm.get('loanAmount')?.touched
"
>
Loan amount must be at least 6 digits.
</div>
</div>
I tried using *ngIf="selectedType === 'purchase' to tell the form which field to target/show next. Also tried the same with a yes/ no option to add the correct field next. I don't which formControlName to use or even if I on the right track.
I also tried creating the steps in my TS file.
Share Improve this question edited Jan 23 at 5:15 Ajeet Verma 3,0813 gold badges17 silver badges29 bronze badges asked Jan 22 at 14:32 MichaelMichael 112 bronze badges1 Answer
Reset to default 0There are few guidelines you can follow to help you achieve this behavior.
First, do not use *ngIf
to hide/show, because when form elements are created/destroyed it can lead to binding issues and other problems.
Instead use [hidden]
to swap with *ngIf
all you need to do is invert the conditional. Suppose *ngIf="test === 'a'
will be changed to [hidden]="test !== 'a'"
.
Group your common fields inside a common div
and apply the hidden condition.
<div [hidden]="test !== 'a'">
<!-- many form fields for a single step -->
</div>
If the grouping looks ugly you can group the form fields as separate components. But you need to have another formGroup
and form inside the child component and the formGroup
should be passed as input to the child component.