I'm using an ngFor in a container to display template rows corresponding to the type, instead of hardcoding the whole form. However I can't get any rows to display. I've tried making an ngif and forcing everything to display.
HTML
<ng-container
*ngFor="let column of filteredColumns"
[ngTemplateOutlet]="getColumnInputType(column)"
[ngTemplateOutletContext]="{ $implicit: column }"
></ng-container>
</ng-container>
<ng-container *ngIf="displayAsRow">
<ng-container *ngFor="let column of filteredColumns">
<c-form-row [title]="column.title" [description]="column.description">
<ng-container [ngTemplateOutlet]="getColumnInputType(column)" [ngTemplateOutletContext]="{ $implicit: column }"></ng-container>
</c-form-row>
</ng-container>
</ng-container>
HTML example of ng-template by type
<ng-template #text let-column>
<div *cHasRole="checkPermissions(column.permissions)" class="d-flex align-items-center justify-content col-3 mb-3">
<mat-form-field [ngClass]="{ 'col-11': column?.description }" appearance="outline" stateChange="onFieldChange(column)">
<mat-label>{{ column.title | translate }} {{ column.validation && column.validation.required ? ' *' : '' }}</mat-label>
<input matInput [formControlName]="column.field" [readonly]="checkColumnReadOnly(column)" />
<mat-hint *ngIf="column.hintLabel">{{ column.hintLabel }}</mat-hint>
<mat-error *ngIf="checkValidationErrors(column, 'required')">
{{ util.formatFormErrorMsg(column.title, 'required') }}
</mat-error>
<mat-error *ngIf="checkValidationErrors(column, 'pattern')">
{{ util.formatFormErrorMsg(column.title, 'pattern') }}
</mat-error>
</mat-form-field>
<h5 *ngIf="column?.description" class="cursor-pointer col-1 pl-0" [ngbTooltip]="column.description" placement="right-center">
<i class="far fa-info-circle text-info"></i>
</h5>
</div>
</ng-template>
Method that is returning the string:
getColumnInputType(column: any): string {
if (column.type.toLowerCase() === 'datetime' || column.type.toLowerCase() === 'date' || column.type.toLowerCase() == 'boolean') {
return column.type.toLowerCase();
}
return column.inputMetaData.inputType.toLowerCase();
}
The problem is that getColumnInputType
returns a string but the ng-container
ngTemplateOutlet
input expects a TemplateRef
.
There are 2 ways to fix this:
getColumnInputType(column: any, textTemplate: TemplateRef): TemplateRef {
if (column.type === 'text') {
return textTemplate;
}
//TODO: what if you don't have a template for the given type
}
so in your HTML you can do something like:
<ng-container
*ngFor="let column of filteredColumns"
[ngTemplateOutlet]="getColumnInputType(column, text)"
[ngTemplateOutletContext]="{ $implicit: column }"
>
</ng-container>
<ng-template #text let-column>
...
</ng-template>
@ViewChild('text') textTemplate: TemplateRef;
getColumnInputType(column: any): TemplateRef {
if (column.type === 'text') {
return this.textTemplate;
}
//TODO: what if you don't have a template for the given type
}
and in the HTML:
<ng-container
*ngFor="let column of filteredColumns"
[ngTemplateOutlet]="getColumnInputType(column)"
[ngTemplateOutletContext]="{ $implicit: column }"
>
</ng-container>
<ng-template #text let-column>
...
</ng-template>