Home > Software design >  How to flip Angular Material Select panel side to make sure it stays inside the screen
How to flip Angular Material Select panel side to make sure it stays inside the screen

Time:12-20

I have a mat-select inside my site's main navbar. It contains a list of currencies and is positioned at the right of the navbar. Since I strictly want to display the currency abbreviation (ex: USD) in my navbar, but want to display a flag icon, currency name, and abbreviation inside the panel, I decided to resize the panel to be larger than the select. This leads to a problem where the panel overflows the screen and is not displayed entirely. I was wondering if there was a simple way to make sure the panel stays inside the browser, in other words, make sure the panel position does not go past the end position of the select.

Current Behavior:

Current Behavior

Desired Behavior:

Desired Behavior

HTML:

<header>
    <mat-toolbar >
      <button mat-icon-button aria-label="Menu Icon">
      <mat-icon>menu</mat-icon>
      </button>
      <span>My Website</span>
      <div >
        <mat-form-field >
          <mat-select name="currency" panelClass="currency-panel" [(value)]="selectedCurrency">
            <mat-select-trigger>{{selectedCurrency}}</mat-select-trigger>
            <mat-option *ngFor="let currency of currencyArr" [value]="currency.key">
              <span ></span> {{currency.key }} - {{ currency.name}}
            </mat-option>
          </mat-select>
        </mat-form-field>
      </div>
    </mat-toolbar>
</header>

CSS:

.navbar {
  background: #ffffff;
  display: flex;
  padding-left: 2rem;
  padding-right: 2rem;
}

.navbar-currency{
  margin-left: auto;
  margin-top: 1.3rem;
}

.currency-select{
  font-size: 0.85rem;
  width: 80px;
}

.currency-panel.mat-mdc-select-panel {
  font-size: 0.85rem;
  min-width: calc(100%   120px)
}

.currency-panel.mat-mdc-select-panel .fi{
  margin-right: 0.1rem;
}

.currency-panel.mat-mdc-select-panel .mat-mdc-option{
  min-height: 36px;
}

CodePudding user response:

Simple Solution

If your Currency Mat-Select is always on the right side of the screen then you could solve this with some css. Set the container position to absolute and the right to zero:

.currency-panel.mat-mdc-select-panel {
  font-size: 0.85rem;
  min-width: calc(100%   120px);
  position: absolute !important;
  right: 0;
}

Mat-Menu Solution

Use Mat-Menu instead, which has a built in handling for the menu positioning. Mat-Select consider the width of your select element as the width of the dropdown select options and that does not require handling the left/right overflow.

You will just need to rewrite your css and you are good to go.

Component Template:

 <button mat-button [matMenuTriggerFor]="menu" >
        <span>{{ selectedCurrency }}</span>
        <mat-icon
          fontIcon="arrow_drop_down"
          style="vertical-align: bottom"
        ></mat-icon>
      </button>

      <mat-menu #menu="matMenu" panelClass="currency-panel">
        <button
          *ngFor="let currency of currencyArr"
          mat-menu-item
          (click)="selectedCurrency = currency.key"
        >
          <span ></span>{{ currency.key }} -
          {{ currency.name }}
        </button>
      </mat-menu>

Component CSS:

.navbar-currency {
  margin-left: auto;
}

.currency-select {
  font-size: 0.85rem;
}

.mat-mdc-menu-panel .fi {
  margin-right: 0.2rem;
}

.currency-panel .mat-mdc-menu-item {
  min-height: 36px;
}

Checkout my stackblitz example

If your Mat-Select will be used on both corners, then you should write your own position handler for the Mat-Select.

  • Related