Reputation: 145
I'm writing a custom form component which is basically a textbox that will change to a label or a textarea depending on a specific property.
So if the custom component is set as read-only, the textbox should be hidden and a label must be displayed.
This hide and show logic work flawlessly. However, the dom element responsible for displaying validation messages throws an error when the control is not found.
<span class="form-control-readonly" *ngIf="readonly == true" #valuelabel>
{{inputModel}}
</span>
<input
*ngIf="readonly != true"
#control="ngModel"
[id]="id"
type="text"
class="form-control"
[placeholder]="caption"
[(ngModel)]="inputModel"
(ngModelChange)="onTextChange()"
[maxlength]="maxLength"
[required]="isRequired === true ? '' : null"
[ngClass]="{'invalid': !control.valid, 'valid': control.valid }">
<div *ngIf="(readonly == false) && (control.invalid && hideFeedback === false)" class="invalid-feedback">
<div *ngIf="(readonly == false) && (control.errors.required)">{{ caption }} is required</div>
<div *ngIf="(readonly == false) && (control.errors.maxlength)">{{ caption }} should be {{ control.errors.maxlength.requiredLength }} characters long </div>
</div>
control.errors in the last div throws "Cannot read property 'invalid' of undefined" error. Probably, because the control doesn't exist in dom.
When ngIf on input is changed to hidden, it begins to work, but I want to achieve it with ngIf.
Upvotes: 0
Views: 3923
Reputation: 5121
Instead of putting ngIf on input, wrap the input and validation div inside another div and apply condition. Thus, the input model will be always visible for the condition below.
<span class="form-control-readonly" *ngIf="readonly == true" #valuelabel>
{{inputModel}}
</span>
<div *ngIf="readonly != true">
<input
#control="ngModel"
[id]="id"
type="text"
class="form-control"
[placeholder]="caption"
[(ngModel)]="inputModel"
(ngModelChange)="onTextChange()"
[maxlength]="maxLength"
[required]="isRequired === true ? '' : null"
[ngClass]="{'invalid': !control.valid, 'valid': control.valid }">
<div *ngIf="(readonly == false) && (control.invalid && hideFeedback===false)" class="invalid-feedback">
<div *ngIf="(readonly == false) && (control.errors.required)">{{ caption }} is required</div>
<div *ngIf="(readonly == false) && (control.errors.maxlength)">{{ caption }} should be {{ control.errors.maxlength.requiredLength }} characters long </div>
</div>
</div>
Upvotes: 0
Reputation: 816
As I can see your code , you can improve it by making readOnly as a boolean and not compare. You can wrap all your code of creating a control under one *ngIf
<span *ngIf="readonly" class="form-control-readonly" #valuelabel>
{{inputModel}}
</span>
<div *ngIf="!readonly">
<input #control="ngModel" [id]="id" type="text"
class="form-control" [placeholder]="caption"
[(ngModel)]="inputModel" (ngModelChange)="onTextChange()"
[maxlength]="maxLength"
[required]="isRequired === true ? '' : null"
[ngClass]="{'invalid': !control.valid, 'valid': control.valid }">
<div *ngIf="(control.invalid && hideFeedback === false)" class="invalid-feedback">
<div *ngIf="(control.errors.required)">{{ caption }} is required</div>
<div *ngIf="(control.errors.maxlength)">{{ caption }} should be {{ control.errors.maxlength.requiredLength }} characters long</div>
</div>
</div>
Upvotes: 0