Angular - ngFor displays all elements in one column
In my angular project I am using ngFor
to display data in a table and for some reason they all appear in the first column. EDIT - this works, but now I'm having problems with mine ngSwitch
. I am getting an error pto-row-edit
saying that it cannot communicate with 'pto' as it is not a known property of 'tr'. I am trying to do this so that the data is displayed in a grid using row-display.component
and then whenever a row is selected, display instead row-edit.component
.
Here's where I call mine row-edit.component
:
<table class="table table-striped table-bordered" *ngIf="empInfo && empInfo.length > selectedEmployee">
<thead>
<tr>
<th>Date</th>
<th>Full/Half</th>
<th>Hours</th>
<th>Scheduled?</th>
<th>Notes</th>
<th>In P/R?</th>
</tr>
</thead>
<tbody>
<ng-container *ngFor="let pto of (ptoData | currentEmployee:empInfo[selectedEmployee].EmpKey)">
<ng-container [ngSwitch]="isRowSelected()">
<ng-container *ngSwitchCase="false">
<tr pto-row-display [pto]="pto" *ngIf="pto.type === selectedType"></tr>
</ng-container>
<ng-container *ngSwitchCase="true">
<tr pto-row-edit [pto]="pto" [rowSelected]="rowSelected" *ngIf="pto.type === selectedType"></tr>
</ng-container>
</ng-container>
</ng-container>
</tbody>
</table>
here my row-edit.component.ts
:
import { Component, OnInit, Input } from '@angular/core';
import { PTOData } from './pto-data';
@Component({
selector: '[pto-row-edit]',
templateUrl: `./row-edit.component.html`,
styleUrls: ['./row-edit.component.css']
})
export class RowEditComponent {
@Input() pto: PTOData[];
}
and here my row-edit.component.html
:
<td><input class='form-control' type="text" id="ptoDate" [ngModel]="pto.date | date: 'MM/dd/y'" (ngModelChange)="pto.date=$event" name="ptoDate" /></td>
<td>
<select class="form-control" id="ptoFullHalf" [(ngModel)]="pto.fullhalf" name="ptoFullHalf">
<option value="full">Full</option>
<option value="AM">AM</option>
<option value="PM">PM</option>
<option value="(full)">(Full)</option>
<option value="(half)">(Half)</option>
</select>
</td>
<td>
<select class="form-control" id="ptoHours" [(ngModel)]="pto.hours" name="ptoHours">
<option value="4">4</option>
<option value="8">8</option>
<option value="-4">-4</option>
<option value="-8">-8</option>
</select>
</td>
<td>
<select class="form-control" id="ptoScheduled" [(ngModel)]="pto.scheduled" name="ptoScheduled">
<option value=""></option>
<option value="advanced">Advanced</option>
<option value="scheduled">Scheduled</option>
<option value="unscheduled">Unscheduled</option>
</select>
</td>
<td><input class='form-control' type="text" id="ptoNotes" [(ngModel)]="pto.notes" name="ptoNotes" /></td>
<td>
<input class="form-check-input" type="checkbox" id="ptoinPR" [(ngModel)]="pto.inPR" name="ptoinPR" />
</td>
I really feel like this should work, and I'm not entirely sure why it doesn't.
source to share
In table
elements, you cannot place a custom element in it. If you add a custom element to an element table
, they will be considered invalid html and that element will be thrown out of the tag table
.
In this case, I recommend that you create a component selector attribute and then move the condition pto.type === selectedType
to CustomPipe ngFor
so we can get rid of ng-container
. Maybe you can extend currentEmployee
Pipe with pto.type === selectedType
(this check). Subsequently directly place pto-row-display
on tr
as in the attribute.
selector: '[pto-row-display]'
And then use it as an attribute
<table class="table table-striped table-bordered" *ngIf="empInfo && empInfo.length > selectedEmployee">
<thead>
<tr>
<th>Date</th>
<th>Full/Half</th>
<th>Hours</th>
<th>Scheduled?</th>
<th>Notes</th>
<th>In P/R?</th>
</tr>
</thead>
<tbody>
<tr
*ngFor="let pto of (ptoData | currentEmployee:empInfo[selectedEmployee].EmpKey):selectedType"
pto-row-display [pto]="pto">
</tr>
</tbody>
</table>
currentEmployee Pipe
import { Pipe, PipeTransform } from '@angular/core';
import { PTOData } from './pto-data';
@Pipe({ name: 'currentEmployee' })
export class CurrentEmployee implements PipeTransform {
transform(allData: PTOData[], key: number, selectedType: any) {
return (allData ? allData.filter(emp => emp.EmpKey == key && emp.type === selectedType) : []);
}
}
source to share