Expand/Collapse table rows - Angular 11 Material
You can use MatExpensionPanel, you've got an example here https://material.angular.io/components/expansion/examples.
Expand/collapse table rows in Angular
For keeping the table row expanded until you click on the row to collapse, you just need boolean flag on each element array. I would suggest to create property under your array as false and set it to toggle on click of row. Also, as @brandon mentioned in comment, your html is invalid. So I modified it a bit.
HTML:
<table class="table">
<tr class="header-row">
<th class="header">Province</th>
</tr>
<tr
class="table-row-not-expanded"
*ngFor="let covenant of covenants; let i = index"
>
<td class="cell" (click)="covenant.isExpanded = !covenant.isExpanded">
<div>{{ covenant.provinceID }}</div>
<div *ngIf="covenant.isExpanded" class="expanded-panel">
<div class="table-container">
<table class="table">
<tr class="header-row">
<th class="header">header 1</th>
<th class="header">header 2</th>
<th class="header">header 3</th>
</tr>
<tr class="table-row">
<td class="cell">1</td>
<td class="cell">2</td>
<td class="cell">3</td>
</tr>
</table>
</div>
</div>
</td>
</tr>
</table>
TS:
import { Component, OnInit, VERSION } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
name = 'Angular ' + VERSION.major;
covenants: any = [
{ provinceID: 1 },
{ provinceID: 2 },
{ provinceID: 3 },
{ provinceID: 4 },
{ provinceID: 5 },
];
openCoverages = false;
indexSelectedCoverage = 1;
ngOnInit() {
this.covenants.forEach((_covenants) => {
_covenants.isExpanded = false;
});
}
selectItemCoverages(index: number) {
//this.openCoverages = this.openCoverages && this.indexSelectedCoverage === index ? false : true;
//this.indexSelectedCoverage = index;
}
}
Play here
Expand and collapse row on button click which is in a td in mat table row
you need add to your search.component.css
tr.example-detail-row {
height: 0;
}
.example-element-detail {
overflow: hidden;
display: flex;
}
.example-element-row td {
border-bottom-width: 0;
}
And remove the (click) in row
//this
<tr mat-row *matRowDef="let search; columns: displayedColumns;"
class="example-element-row"
[class.example-expanded-row]="expandedElement === search"
(click)="expandedElement = expandedElement === search ? null : search">
`enter code here`
</tr>
become as
<tr mat-row *matRowDef="let search; columns: displayedColumns;"
class="example-element-row"
[class.example-expanded-row]="expandedElement === search">
</tr>
See this fool stackblitz
Angular material table collapse/expand complete table so only header is visible
Solution:
When tapping collapse, I assign an empty array to the data source of that table. when clicking expands I reassign the original array to the data source of that table. This way my header&footer cells which contain totals for the table are still visible but the inner cells are not.
Something like the code below should allow this behavior:
collapse(index: number) {
if (this.contracts[index].tabledatasource.data.length == 0) {
this.contracts[index].tabledatasource = new MatTableDataSource(this.stockArray[index]);
} else {
this.contracts[index].tabledatasource = new MatTableDataSource([]);
}
}
Expandable table rows in angular 4 with angular material
As mentioned here by Andrew Seguin this is already feasible out of the box: using the when
predicate.
See this example: https://stackblitz.com/edit/angular-material-expandable-table-rows (thx to Lakston)
Inside of the mat-table
tag you have to use the mat-row
component with a matRipple
directive. When you click on a row the row element will be assigned to the expandedElement
variable:
<mat-row *matRowDef="let row; columns: displayedColumns;"
matRipple
class="element-row"
[class.expanded]="expandedElement == row"
(click)="expandedElement = row">
</mat-row>
But now we have to add our expanded row, that is hidden by default and will be shown if the user clicks on the row above:
<mat-row *matRowDef="let row; columns: ['expandedDetail']; when: isExpansionDetailRow"
[@detailExpand]="row.element == expandedElement ? 'expanded' : 'collapsed'"
style="overflow: hidden">
</mat-row>
Important is here the already mentioned when
predicate. This calls a isExpansionDetailRow
function that is defined in the component itself and checks if the row has a detailRow
property:
isExpansionDetailRow = (row: any) => row.hasOwnProperty('detailRow');
Since RC0 the first param is the index:
isExpansionDetailRow = (i: number, row: any) => row.hasOwnProperty('detailRow');
If you want to have an expanded view for every row, you have to add an "ExpansionDetailRow" identified by the detailRow
property for every row like this:
connect(): Observable<Element[]> {
const rows = [];
data.forEach(element => rows.push(element, { detailRow: true, element }));
return Observable.of(rows);
}
If you would log the rows
variable to the console output, it will look like this:
Mat Table expandable rows (sorting, pagination and filtering)
Hide/show a table row when clicking on a link in Angular2
The problem you are facing here is that you are associating a toggle to an element inside a for loop without actually creating different references. This means that all the generated table rows will point to the same reference so when you click one link it will affect multiple.
Since you are already getting the index
on the ngFor
loop you should associate that index to the toggle references. The result would become something like this
toggle_1[total.projectGroup]
toggle_2[total.projectGroup]
This way the reference for the action would be kept on each row of the table.
But to simplify what it seems to be your goal you could just have
(click) = “toggle[i] = !toggle[i]”
And then where you have the hidden checking the toggle I would also replace
[hidden]="!toggle[total.projectGroup]"
With
[hidden]="!toggle[i]”
I believe you just need the template flags. Unless you need some more complex behaviour I don't think you need the component function at all
I have also noticed that you have the second ngFor
loop without an index. This will cause issues because when you set the indProjects
property it will have the same value for all the rows. So you need to pass the index to your expand(total.projectGroup, i)
function and in the template when doing the loop you will need to read from
<tr *ngFor="let pjt of indProjects[i]" class="table-condensed">
This way you will for sure have unique list per row
How to expand and collapse table row on click
In your (click)
event you are only setting expandedElement
so it will always get selected. You need to instead toggle the value so the row can be deselected as well.
Change your (click)
function to the following
<mat-row *matRowDef="let row; columns: displayedColumns;"
matRipple
class="element-row"
[class.expanded]="expandedElement == row"
(click)="expandedElement = expandedElement === row ? null : row">
</mat-row>
Related Topics
Regex to Allow Only Certain Special Characters and Restrict Underscore
How to Restrict Past Dates in Html5 Input Type Date
Loading Screen Gets Stuck While Processing Http Request
Disable/Hide Download Button in Iframe on Default Pdf Viewer
How to Refresh Form Page After Post Request
How to Simulate Key Press Events Programmatically
How to Disable Print-Screen Functionality for a Webpage in All Browsers
How to Reload Datatables from Another Ajax Request With Onclick
Onclick Button Get from Database and Display on a Input Field Live
How to Include External JavaScript Library in Reactjs
How to Save Binary Buffer to Png File in Nodejs
Javascript: Location.Href to Open in New Window/Tab
Angular 2 Concatenate Variable in Interpolation
How to Close Toggle Menu When Clicking Navigation Item Anchor Link
Pass Dynamic Object in Onclick - Javascript/Jquery