1

Stack Blitz Demo

I am having trouble figuring out how to get my code to behave as needed.

As the demo shows I have a table that when the add button is clicked a new row is added. Once the table rows reach a certain height (say for example after adding 5 rows) I need a vertical scroll bar to display and at the same time I need to maintain a sticky header. Basically I need to set the table rows to a fixed height.

The attached screen shot shows where I would like the scroll bar to display. Apologies for the shaky highlight.

The HTML looks looks like this

<div class="table-container">
  <table mat-table [dataSource]="dataSource">
    <ng-container matColumnDef="category">
      <th mat-header-cell *matHeaderCellDef >Category</th>
      <td mat-cell *matCellDef="let code" >
        <mat-form-field class="code">
          <mat-select>
            <mat-option *ngFor=" let category of categories" [value]="category.code" class="dropdownpPopUp"  (keydown.ArrowDown)="onDown()">{{category.code}}</mat-option>
          </mat-select>
        </mat-form-field>
      </td>
    </ng-container>
    <ng-container matColumnDef="type">
      <th mat-header-cell *matHeaderCellDef>Type</th>
      <td mat-cell *matCellDef="let code" >
        <mat-form-field class="type">
          <mat-select >
            <mat-option *ngFor=" let type of types" [value]="type.code" class="dropdownpPopUp"  (keydown.ArrowDown)="onDown()">{{type.code}}</mat-option>
          </mat-select>
        </mat-form-field>
      </td>
    </ng-container>
    <ng-container matColumnDef="additionalCode" class="parent" >
      <th mat-header-cell *matHeaderCellDef>Additional Code</th>
      <td mat-cell *matCellDef="let element" class="parent" >
        <mat-form-field class="type">
          <input matInput (keyup)="toggleLookup($event)" autocomplete="off" (keydown.ArrowDown)="onDown()">
        </mat-form-field>
        <div *ngIf="expanded" class="child">Yah it expanded
          <button (click)="expanded = false">Close</button>
        </div>
      </td>
    </ng-container>
    <ng-container matColumnDef="ref">
      <th mat-header-cell *matHeaderCellDef>Reference</th>
      <td mat-cell *matCellDef="let element" >
        <mat-form-field>
          <input matInput [(ngModel)]="element.type"  (keydown.ArrowDown)="onDown()" autocomplete="off">
        </mat-form-field>
      </td>
    </ng-container>
    <ng-container matColumnDef="add">
      <th mat-header-cell *matHeaderCellDef>
        <button mat-icon-button (click)="addRow()" matTooltip="Add Row">
          <mat-icon>add</mat-icon>
        </button>
      </th>
      <td mat-cell *matCellDef="let code; let i = index;">
        <button mat-icon-button (click)="removeAt(i)" matTooltip="Remove Row">
          <mat-icon>clear</mat-icon>
        </button>
      </td>
    </ng-container>
    <tr mat-header-row *matHeaderRowDef="columns"></tr>
    <tr mat-row *matRowDef="let rows; columns: columns;"></tr>
  </table>
   <div *ngIf="dataSource.filteredData.length > 0" > <mat-paginator [pageSizeOptions]="[5]" showFirstLastButtons class="paginator"></mat-paginator></div>
</div>

Component Add Function

addRow() {
    this.doAddRow();
    this.expanded = false;
  }
  private doAddRow() {
    ELEMENT_DATA.push({ code: '', type: '', reference: '' });
    this.dataSource = new MatTableDataSource(ELEMENT_DATA);
  }

enter image description here

2
  • please add here some of your code and not only link(the link can removed and in future other user won't understand your question ) Commented May 30, 2019 at 9:20
  • Updated as requested Commented May 30, 2019 at 9:56

2 Answers 2

2

what you have to do is add a div outside of your table and provide a min-height property.

app.component.css

.main-table{
  max-height:42vh;
  overflow-y:scroll;
  overflow-x:hidden;
}

app.component.html

<ol>
  <li>Select + to add rosw</li>
</ol> 
<p>After 5 new rows added a vertical scroll bar should aprear and when srolling the header row should still be visible</p>
<div class="table-container">
  <div class="main-table">
  <table mat-table [dataSource]="dataSource">
    <ng-container matColumnDef="category">
      <th mat-header-cell *matHeaderCellDef >Category</th>
      <td mat-cell *matCellDef="let code" >
        <mat-form-field class="code">
          <mat-select>
            <mat-option *ngFor=" let category of categories" [value]="category.code" class="dropdownpPopUp"  (keydown.ArrowDown)="onDown()">{{category.code}}</mat-option>
          </mat-select>
        </mat-form-field>
      </td>
    </ng-container>
    <ng-container matColumnDef="type">
      <th mat-header-cell *matHeaderCellDef>Type</th>
      <td mat-cell *matCellDef="let code" >
        <mat-form-field class="type">
          <mat-select >
            <mat-option *ngFor=" let type of types" [value]="type.code" class="dropdownpPopUp"  (keydown.ArrowDown)="onDown()">{{type.code}}</mat-option>
          </mat-select>
        </mat-form-field>
      </td>
    </ng-container>
    <ng-container matColumnDef="additionalCode" class="parent" >
      <th mat-header-cell *matHeaderCellDef>Additional Code</th>
      <td mat-cell *matCellDef="let element" class="parent" >
        <mat-form-field class="type">
          <input matInput (keyup)="toggleLookup($event)" autocomplete="off" (keydown.ArrowDown)="onDown()">
        </mat-form-field>
        <div *ngIf="expanded" class="child">Yah it expanded
          <button (click)="expanded = false">Close</button>
        </div>
      </td>
    </ng-container>
    <ng-container matColumnDef="ref">
      <th mat-header-cell *matHeaderCellDef>Reference</th>
      <td mat-cell *matCellDef="let element" >
        <mat-form-field>
          <input matInput [(ngModel)]="element.type"  (keydown.ArrowDown)="onDown()" autocomplete="off">
        </mat-form-field>
      </td>
    </ng-container>
    <ng-container matColumnDef="add">
      <th mat-header-cell *matHeaderCellDef>
        <button mat-icon-button (click)="addRow()" matTooltip="Add Row">
          <mat-icon>add</mat-icon>
        </button>
      </th>
      <td mat-cell *matCellDef="let code; let i = index;">
        <button mat-icon-button (click)="removeAt(i)" matTooltip="Remove Row">
          <mat-icon>clear</mat-icon>
        </button>
      </td>
    </ng-container>
    <tr mat-header-row *matHeaderRowDef="columns"></tr>
    <tr mat-row *matRowDef="let rows; columns: columns;"></tr>
  </table>
  </div>
   <div *ngIf="dataSource.filteredData.length > 0" > <mat-paginator [pageSizeOptions]="[5]" showFirstLastButtons class="paginator"></mat-paginator></div>
</div>
Sign up to request clarification or add additional context in comments.

Comments

2

Actually, Angular Material documentation has covered that.

By using position: sticky styling, the table's rows and columns can be fixed so that they do not leave the viewport even when scrolled. The table provides inputs that will automatically apply the correct CSS styling so that the rows and columns become sticky.

You just need to make the following changes to your <tr> tag with the mat-header-row directive.

<tr mat-header-row *matHeaderRowDef="columns; sticky: true"></tr>

In addition, you will need to edit your container class around your table to include the following properties:

.table-container {
  height: 400px;
  overflow: auto;
  /*
  other CSS properties
   */
}

This will allow your material datatable to have a sticky header. Here is the demo provided by the official documentation.

1 Comment

Thanks, I did try that and you're quite right that's how the official documentation shows describes how to accomplish this generally. However, Its not quite how I would like my table to render. I have added a screen shot describing were I would like the scroll bar to be displayed. I'm hoping its possible.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.