Angular 5 Material centering a span into a mat-header-cell - html

On my angular5 application I am using material table to display some data.
Into a mat-header-cell I am having a span and a img together and trying to align them properly.
Here how it looks right now :
Here the piece html code :
<ng-container matColumnDef="batchState">
<mat-header-cell *matHeaderCellDef style="border: 1px solid white;">
<span style="border: 1px solid white;">Batch state </span>
<img style="border: 1px solid white;" src='../../assets/filter_list.png' (click)="filterByState()"
matTooltip="Filter by state" />
</mat-header-cell>
<mat-cell *matCellDef="let inst">
{{inst.batchState}}
</mat-cell>
</ng-container>
I want my span to be displayed at the center-left of the cell, tried text-align:center; left:0px; and padding-top: 25%; padding-bottom: 25% (inside my span element) but those css did not work, any way to achieve that?

Solution found adding css to the mat-header-cell -> display: flex; align-items: center;
<ng-container matColumnDef="batchState">
<mat-header-cell *matHeaderCellDef style="border: 1px solid white;display: flex; align-items: center;">
<span style="border: 1px solid white;">Batch state </span>
<img style="border: 1px solid white;" src='../../assets/filter_list.png' (click)="filterByState()"
matTooltip="Filter by state" />
</mat-header-cell>
<mat-cell *matCellDef="let inst">
{{inst.batchState}}
</mat-cell>
</ng-container>

Related

Angular Material Table displays uneven width on the first colum

I created a Material Table where I give the user the option to add or remove columns. The table can also sort, arrange columns, and has a sticky actions column. I want the table to take 100% of the available width space and scroll on the table when there are too many columns instead of fitting them to the screen size. The problem that I have is when only a few columns are displayed, for some reason the first column takes a lot more space then the other columns. I've tried many things and the only solution that I've found was making the table-layout: fixed but this will break the scrolling of overflow-x: scroll which is not what the users want. Any suggestions?
<mat-table [dataSource]="dataSource" class="mat-elevation-z8" matSort cdkDropList cdkDropListOrientation="horizontal" (cdkDropListDropped)="drop($event)">
<ng-container [matColumnDef]="column" *ngFor="let column of displayedColumns">
<ng-container *ngIf="column !== 'Actions'; else action">
<th [ngClass]="{'border': hasTableBorders}" mat-header-cell cdkDrag [hidden]="column == 'Id'" *matHeaderCellDef mat-sort-header>{{ column }}</th>
<td [ngClass]="{'border': hasTableBorders}" mat-cell [hidden]="column == 'Id'" *matCellDef="let element">{{ element[column] | shorten:22 }}</td>
</ng-container>
<ng-template #action>
<th mat-header-cell *matHeaderCellDef>Actions</th>
<td mat-cell class="m-0 p-0" *matCellDef="let element">
<h3 class="btn bi bi-pencil-fill" matTooltip="Quick Edit" (click)="onQuickEdit(element.Id)" [matTooltipPosition]="'above'"></h3>
<h2 class="btn bi bi-eye-fill" matTooltip="View" (click)="onFullEdit(element.Id)" [matTooltipPosition]="'above'"></h2>
</td>
</ng-template>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
<tr [ngClass]="{'alternate-row-colors': isAlternateRowColor}" mat-row *matRowDef="let row; columns: columnsToDisplay"></tr>
<tr class="mat-row" *matNoDataRow>
<td class="mat-cell" colspan="4">No data matching the filter "{{input.value}}"</td>
</tr>
</mat-table>
css
.mat-table {
overflow-x: scroll;
width: 100%;
}
.mat-cell, .mat-header-cell {
word-wrap: initial;
display: table-cell;
padding: 0px 10px;
line-break: unset;
width: 100%;
white-space: nowrap;
overflow: hidden;
vertical-align: middle;
}
.mat-row,
.mat-header-row {
display: table-row;
}
Looks good with many columns
Bad display

Space between sticky header rows in Angular mat table in Chrome

I have a mat-table with 2 sticky headers. The code works fine in Firefox but in Chrome, when I scroll down, I can see the text in the background of 2 headers. There is some space between header cells that do not appear in the Firefox browser but does appear in chrome.
As an example, I have added the table background as red, and as you can see the red lines appear between the first 2 rows. Also, there are no borders. table-image
The Code is as below:
HTML Code:
<div>
<button mat-raised-button (click)="tables.push(tables.length)">Add table</button>
<button mat-raised-button (click)="tables.pop()">Remove table</button>
</div>
<div>
Sticky Headers:
<mat-button-toggle-group multiple [value]="['header-1']" #stickyHeaders="matButtonToggleGroup"
class="example-sticky-toggle-group">
<mat-button-toggle value="header-1"> Row 1 </mat-button-toggle>
<mat-button-toggle value="header-2"> Row 2 </mat-button-toggle>
</mat-button-toggle-group>
</div>
<div>
Sticky Footers:
<mat-button-toggle-group multiple [value]="['footer-1']" #stickyFooters="matButtonToggleGroup"
class="example-sticky-toggle-group">
<mat-button-toggle value="footer-1"> Row 1 </mat-button-toggle>
<mat-button-toggle value="footer-2"> Row 2 </mat-button-toggle>
</mat-button-toggle-group>
</div>
<div>
Sticky Columns:
<mat-button-toggle-group multiple [value]="['position', 'symbol']" #stickyColumns="matButtonToggleGroup"
class="example-sticky-toggle-group">
<mat-button-toggle value="position"> Position </mat-button-toggle>
<mat-button-toggle value="name"> Name </mat-button-toggle>
<mat-button-toggle value="weight"> Weight </mat-button-toggle>
<mat-button-toggle value="symbol"> Symbol </mat-button-toggle>
</mat-button-toggle-group>
</div>
<div class="example-container mat-elevation-z8">
<table mat-table [dataSource]="dataSource" *ngFor="let table of tables">
<ng-container matColumnDef="position" [sticky]="isSticky(stickyColumns, 'position')">
<mat-header-cell *matHeaderCellDef> Position </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.position}} </mat-cell>
<mat-footer-cell *matFooterCellDef> Position Footer </mat-footer-cell>
</ng-container>
<ng-container matColumnDef="name" [sticky]="isSticky(stickyColumns, 'name')">
<mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
<mat-footer-cell *matFooterCellDef> Name Footer </mat-footer-cell>
</ng-container>
<ng-container matColumnDef="weight" [stickyEnd]="isSticky(stickyColumns, 'weight')">
<mat-header-cell *matHeaderCellDef> Weight </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.weight}} </mat-cell>
<mat-footer-cell *matFooterCellDef> Weight Footer </mat-footer-cell>
</ng-container>
<ng-container matColumnDef="symbol" [stickyEnd]="isSticky(stickyColumns, 'symbol')">
<mat-header-cell *matHeaderCellDef> Symbol </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.symbol}} </mat-cell>
<mat-footer-cell *matFooterCellDef> Symbol Footer </mat-footer-cell>
</ng-container>
<ng-container matColumnDef="filler">
<mat-header-cell *matHeaderCellDef> Filler header cell </mat-header-cell>
<mat-cell *matCellDef="let element"> Filler data cell </mat-cell>
<mat-footer-cell *matFooterCellDef> Filler footer cell </mat-footer-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns; sticky: isSticky(stickyHeaders, 'header-1')"></mat-header-row>
<mat-header-row *matHeaderRowDef="displayedColumns; sticky: isSticky(stickyHeaders, 'header-2')"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
<mat-footer-row *matFooterRowDef="displayedColumns; sticky: isSticky(stickyFooters, 'footer-1')"></mat-footer-row>
<mat-footer-row *matFooterRowDef="displayedColumns; sticky: isSticky(stickyFooters, 'footer-2')"></mat-footer-row>
</table>
</div>
CSS Code
.example-container {
height: 400px;
overflow: auto;
}
.mat-table-sticky {
background: #59abfd;
opacity: 1;
border-collapse: collapse;
}
.mat-table {
background-color: red;
border-collapse: collapse;
}
.example-sticky-toggle-group {
margin: 8px;
}
.mat-column-filler {
padding: 0 8px;
font-size: 10px;
text-align: center;
}
.mat-header-cell,
.mat-footer-cell,
.mat-cell {
min-width: 80px;
box-sizing: border-box;
}
.mat-header-row,
.mat-footer-row,
.mat-row {
min-width: 1920px; /* 24 columns, 80px each */
}
.mat-table-sticky-border-elem-top {
border-bottom: 2px solid midnightblue;
}
.mat-table-sticky-border-elem-right {
border-left: 2px solid midnightblue;
}
.mat-table-sticky-border-elem-bottom {
border-top: 2px solid midnightblue;
}
.mat-table-sticky-border-elem-left {
border-right: 2px solid midnightblue;
}
I have already tried border-collapse but that does not work.
Add min-width: 200px;
As per your requirement, to the .mat-cell and .mat-header-cell. That will do

Flexbox div not taking up entire horizontal space

I have an angular page with 3 components i'm trying to get to fill the entire horizontal space. Currently the parent flexbox div is not expanding to the full length, even though I have width: 100% on it. I am able to change the width using pixel values instead, however I have no idea how wide the viewport is going to be when the page is loaded. I have tried setting the margin and padding to 0, making sure the child flexdivs widths add up to 100%, etc...
Relevant html:
<div fxLayout="row" fxLayoutGap="15px" id="bottomContainer">
<div fxFlex="1 0 40%"><mat-card gdArea="chart">
<mat-card-subtitle>Messages Flagged <br>{{period}}<button mat-icon-button [matMenuTriggerFor]="menu"><mat-icon>more_vert</mat-icon></button></mat-card-subtitle>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="period = 'Week'; periodInt = 0; changeMessagesFlaggedChartPeriod('Week')">Week</button>
<button mat-menu-item (click)="period = 'Month'; periodInt = 1; changeMessagesFlaggedChartPeriod('Month')">Month</button>
<button mat-menu-item (click)="period = 'Year'; periodInt = 2; changeMessagesFlaggedChartPeriod('Year')">Year</button>
</mat-menu>
<mat-card-content gdAreas="chart | list" gdRows="auto">
<div style="display: block">
<canvas baseChart
[datasets]="this.currentMessagesFlaggedDataset"
[labels]="this.MESSAGES_FLAGGED_LABELS"
chartType="radar"
[options]="this.messagesFlaggedChartOptions"
[colors]="this.channelData.chartColors"
height="100%"
width="100%"
></canvas>
</div>
</mat-card-content>
</mat-card></div>
<div fxFlex="1 1 30%"><mat-card class="mat-elevation-z2 channelUserTableContainer">
<mat-card-subtitle>Most Negative Users</mat-card-subtitle>
<table mat-table class="channelUserTable" [dataSource]="channelData.negativeUsers">
<!-- Username column -->
<ng-container matColumnDef="username">
<th mat-header-cell *matHeaderCellDef>Username</th>
<td mat-cell *matCellDef="let element"> {{element.username}}</td>
</ng-container>
<!-- Number of flags column -->
<ng-container matColumnDef="numFlags">
<th mat-header-cell class="textAlignRight" *matHeaderCellDef>Number of Flags</th>
<td mat-cell class="textAlignRight" *matCellDef="let element"> {{element.numFlags}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="userTableColumns"></tr>
<tr mat-row *matRowDef="let row; columns: userTableColumns;"></tr>
</table>
</mat-card></div>
<div fxFlex="1 1 30%"><mat-card class="mat-elevation-z2 channelUserTableContainer">
<mat-card-subtitle>Most Positive Users</mat-card-subtitle>
<table mat-table class="channelUserTable" [dataSource]="channelData.positiveUsers">
<!-- Username column -->
<ng-container matColumnDef="username">
<th mat-header-cell *matHeaderCellDef>Username</th>
<td mat-cell *matCellDef="let element"> {{element.username}}</td>
</ng-container>
<!-- Number of flags column -->
<ng-container matColumnDef="numFlags">
<th mat-header-cell class="textAlignRight" *matHeaderCellDef>Number of Flags</th>
<td mat-cell class="textAlignRight" *matCellDef="let element"> {{element.numFlags}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="userTableColumns"></tr>
<tr mat-row *matRowDef="let row; columns: userTableColumns;"></tr>
</table>
</mat-card></div>
</div>
CSS:
padding-left: 16px;
padding-top: 16px;
}
#channelHeaderText {
font-size: x-large;
font-weight: bold;
}
.mindChartNoMargin :nth-child(1) {
margin: 0;
}
.channelUserTable {
width: 100%;
}
.channelUserTableContainer {
background-color: white;
}
.textAlignRight {
text-align: right;
}
#bottomContainer {
width: 100%;
}
Help is much appreciated
Try moving the width to the container instead, also try making the container a flexbox and the items flex too.
.channelUserTableContainer {
background-color: white;
width: 100%;
display: flex;
}
.channelUserTable {
display: flex;
}
I like to add a dotted line to understand how the flexboxes are working so you could also add a dotted border
border: dotted;

Material pagination dropdown out of place

Issue
I am currently implementing a <mat-table> with a <mat-paginator> attached to it. The only problem is that the dropdown for items per page is being offset to the left. For what seems like outside of the Bootstrap container.
Here is an image of what is happening. You can see the location of the dropdown and the location of the items are completely wrong.
Code
My entire site is inside of a bootstrap container so my app.component.html basically looks like this:
<app-header></app-header>
<div class="container mt-3">
<router-outlet></router-outlet>
</div>
<app-footer></app-footer>
The page in questions is just a simple material table with the pagination added to the bottom.
<div class="row">
<div class="col-md-12">
<mat-table *ngIf="items" [dataSource]="items" matSort>
<!-- ID Column -->
<ng-container matColumnDef="type">
<mat-header-cell *matHeaderCellDef mat-sort-header> Type </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.type}} </mat-cell>
</ng-container>
<!-- Provider Column -->
<ng-container matColumnDef="provider">
<mat-header-cell *matHeaderCellDef mat-sort-header> Provider </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.provider}} </mat-cell>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="url">
<mat-header-cell *matHeaderCellDef mat-sort-header> URL </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.url}} </mat-cell>
</ng-container>
<!-- Color Column -->
<ng-container matColumnDef="country">
<mat-header-cell *matHeaderCellDef mat-sort-header> Country </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.country}} - <span class="flag-icon flag-icon-{{row.country | lowercase}}"></span> </mat-cell>
</ng-container>
<!-- Color Column -->
<ng-container matColumnDef="updated_on">
<mat-header-cell *matHeaderCellDef mat-sort-header> Updated </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.updated_on}} </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="['type', 'provider', 'url', 'country', 'updated_on']"></mat-header-row>
<mat-row *matRowDef="let row; columns: ['type', 'provider', 'url', 'country', 'updated_on']">
</mat-row>
</mat-table>
<mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
</div>
</div>
It seems that some css are needed. Just try including in your style.css or style.scss the line
#import "../node_modules/#angular/material/prebuilt-themes/indigo-pink.css";
I can solve this problem finally =D We have known that some css code of Angular overwritten the original css code of the pagination which work with the cdk-overlay-container. That's why I have tried to copy the code out of the file #angular/cdk/overlay-prebuilt.css in my own css-File what has fixed the bug. Afterwards I have looked which components I really needed and that's it:
//Add this to your css/scss File
::ng-deep {
.cdk-overlay-container,
.cdk-global-overlay-wrapper {
pointer-events: none;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
.cdk-overlay-container {
position: fixed;
z-index: 1000;
}
.cdk-overlay-pane {
position: absolute;
pointer-events: auto;
box-sizing: border-box;
z-index: 1000;
display: flex;
max-width: 100%;
max-height: 100%;
}
}
Now you have the original pagination of Angular if you want a non transparent dropbox selection, add the following lines to .cdk-overlay-pane
background-color: white;
border: 1px solid rgba(128, 128, 128);
import { MatPaginatorModule } from '#angular/material/paginator';
Have you imported Material Pagination Module? If not then please import and try again. Thanks
In most projects, be it boostrap-themed or material-themed, there is usually a theme folder, you would have files like theme-variable.scss and theme.scss for Bootstrap projects, while in material projects, you'd find material-theme.css or material-theme.scss.
The last two files are very important for angular-material components to be rendered properly, even after importing the modules responsible for the component, you need the files mentioned above.
After ensuring you have those two files, you want to import them in your styles.css file with this line: #import './theme/material-theme.css';
Once the above steps are taken, the table or whichever angular-material component will render properly.

CSS Html: Text not truncating enough causing container to grow

I have a angular-material card inside here is a mat-table, containing notes.
HTML And CSS Below
<div fxLayout="column" style="flex: 1;">
<mat-card class="card-info" style="margin-right: 10px; max-height: 167px;">
<mat-card-content>
<div class="example-container">
<mat-table #table [dataSource]="notes">
<!-- Name Column -->
<ng-container matColumnDef="date">
<mat-header-cell *matHeaderCellDef> Date </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.created | date }} </mat-cell>
</ng-container>
<!-- Weight Column -->
<ng-container matColumnDef="subject">
<mat-header-cell *matHeaderCellDef> Subject </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.subject}} </mat-cell>
</ng-container>
<!-- Symbol Column -->
<ng-container matColumnDef="note">
<mat-header-cell *matHeaderCellDef> Note </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.value}} </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</div>
</mat-card-content>
</mat-card>
</div>
CSS:
.example-container {
display: flex;
flex-direction: column;
max-height: 500px;
min-width: 300px;
}
.mat-table {
overflow: auto;
max-height: 500px;
}
mat-header-cell, mat-cell {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
Although the text inside the cell does truncate, it doesn't truncate enough and causes the card to grow. I don't want to put a max-width, as I want it to flex to fill remainder of the screen.
Here is an image of how it looks:
As you can see it makes the card grow off the screen.