I tried for the past 2 weeks to get this code to work. I searched and tried the solution from Philipp Kief which is a solution that I could partly understand. I'm new.
And I also studied these other solutions. Ho Wei Lip 2 and Ho Wei Lip 3
Unfortunately, I'm stuck and I don't know why the table doesn't expand. I don't get an error, but it seems to (click)
and MatRipple
seems to respond. I also tried, material expansion panel, but it seems off topic. Could someone point me in the right direction? Thank you.
import { Component, OnInit, ViewChild } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { DataSource } from '@angular/cdk/collections';
import { Incident } from './interface';
import {
MatSort,
MatTableDataSource,
ICON_REGISTRY_PROVIDER,
MatPaginator
} from '@angular/material';
import {
animate,
state,
style,
transition,
trigger
} from '@angular/animations';
import { switchMap, concatMap } from 'rxjs/operators';
import { interval } from 'rxjs';
import { timer } from 'rxjs/observable/timer';
@Component({
selector: 'app-incident',
templateUrl: './incident.component.html',
styleUrls: ['./incident.component.css'],
animations: [
trigger('detailExpand', [
state(
'collapsed',
style({ height: '0px', minHeight: '0', visibility: 'hidden' })
),
state('expanded', style({ height: '*', visibility: 'visible' })),
transition(
'expanded <=> collapsed',
animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')
)
])
]
})
export class IncidentComponent implements OnInit {
constructor(private http: HttpClient) {}
@ViewChild(MatSort) sort: MatSort;
private serviceUrl = 'http://localhost:3001/api-incidents/55';
FIVE_MINUTES = 5 * 60 * 1000;
panelOpenState = false;
incidents: Incident;
incidentParseArray: any;
incidents_sortable: any;
displayedColumns: string[] = [
// 'statusIcon',
'incident'
// 'INCIDENT_TYPE',
// 'MODIFICATION_DATE',
// 'prognosisIcon'
];
dataSource = new MatTableDataSource<Incident>(this.incidentParseArray);
expandedElement: any;
isExpansionDetailRow = (i: number, row: Object) =>
row.hasOwnProperty('detailRow')
ngOnInit() {
timer(0, this.FIVE_MINUTES).subscribe(() => {
this.http.get<Incident>(this.serviceUrl).subscribe(response => {
this.incidents = response;
const incidentArray = Object.values(this.incidents);
// console.log('array ===> ', incidentArray);
this.incidentParseArray = incidentArray.map(
({
INCIDENT_NAME,
eStatus,
eSTATUS_COLOR,
INCIDENT_TYPE,
ePROGNOSIS,
ePROGNOSIS_COLOR,
MODIFICATION_DATE
}) => {
const [incident, aux] = INCIDENT_NAME.split(/-\s+/, 2);
const [status, active] = eStatus.split(/-\s+/, 2);
const [junk0, statusColor, junk1] = eSTATUS_COLOR.split(/\./, 3);
const [junk2, prognosisColor, junk3] = ePROGNOSIS_COLOR.split(
/\./,
3
);
const statusIcon = assignStatusIcon(statusColor);
const prognosisIcon = assignPrognosisIcon(ePROGNOSIS);
const prognosisColorText = assignPrognosisColor(prognosisColor);
const statusColorText = assignStatusColor(statusColor);
return {
incident,
status,
statusColor,
statusIcon,
statusColorText,
prognosisColor,
prognosisColorText,
INCIDENT_TYPE,
ePROGNOSIS,
prognosisIcon,
MODIFICATION_DATE
};
}
);
});
});
}
}
function assignStatusIcon(color) {
let icon = '';
if (color === 'gray') {
icon = 'brightness_1';
} else if (color === 'green') {
icon = 'brightness_1';
} else {
icon = 'broken_image';
}
return icon;
}
function assignStatusColor(color) {
let pcolor = '';
if (color === 'gray') {
pcolor = 'grey-text';
} else if (color === 'green') {
pcolor = '#00c853 green-text accent-4';
} else {
pcolor = 'black-text';
}
return pcolor;
}
function assignPrognosisIcon(str) {
let icon = '';
if (str === 'Monitoring') {
icon = 'remove_red_eye';
} else if (str === 'Response') {
icon = 'directions_walk';
} else {
icon = 'broken_image';
}
return icon;
}
function assignPrognosisColor(color) {
let pcolor = '';
if (color === 'grey') {
pcolor = 'grey-text';
} else if (color === 'red') {
pcolor = 'red-text';
} else {
pcolor = 'black-text';
}
return pcolor;
}
and this is my template.
<mat-table #table [dataSource]="incidentParseArray" matSort class="z-depth-2 table-font-size
mat-display-10">
<ng-container matColumnDef="incident">
<th mat-header-cell *matHeaderCellDef class="table-font-size" [ngClass]="'customWidthClass'">
INCIDENT </th>
<td mat-cell *matCellDef="let element" class="table-font-size mat-cell" [ngClass]="'customWidthClass'">
{{element.incident}} </td>
</ng-container>
<!-- EXPANDED CONTENT - TEST -->
<ng-container matColumnDef="expandedDetail">
<mat-cell *matCellDef="let element">
The symbol for {{element.INCIDENT_TYPE}} is
TEST TEST TEST
</mat-cell>
</ng-container>
<mat-row *matRowDef="let row; columns: ['expandedDetail']; when: isExpansionDetailRow"
[@detailExpand]="row.element == expandedElement ? 'expanded' : 'collapsed'"
style="overflow: hidden">
</mat-row>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row mat-row *matRowDef="let row; columns: displayedColumns;"
matRipple
class="element-row"
[class.expanded]="expandedElement == row"
(click)="expandedElement= row">
</mat-row>
</mat-table>
The key to this working is when: isExpansionDetailRow
which calls the following function expression... it essentially evaluates each object in the MatTableDataSource
for a property of detailRow
and returns true
if present.
isExpansionDetailRow = (i: number, row: Object) =>
row.hasOwnProperty('detailRow')
In the following stackblitz notice this block of code, this is essentially taking the original element and concatenating it with a property called detailRow
and a redundant copy of the element to be used to render data in the expanded row. (since they are separate and do not use the same data object) rows.push(element, { detailRow: true, element })
export class ExampleDataSource extends DataSource<any> {
/** Connect function called by the table to retrieve one stream containing the data to render. */
connect(): Observable<Element[]> {
const rows = [];
ELEMENT_DATA.forEach(element => rows.push(element, { detailRow: true, element }));
console.log(rows);
return of(rows);
}
disconnect() { }
}
Stackblitz
https://stackblitz.com/edit/div-on-click-qqcdmx?embed=1&file=app/table-basic-example.ts
During your incidentArray.map()
in the NgOnInit
make sure you are adding this property to the rows that you want to be expandable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With