3
votes

Currently building an application in Angular 4.1.3, angular-cli 1.1.1, angular material 2.0.0

The normal md-select overlay behavior seems to shift the position of the overlay up or down so that the current selection is located on top of the respective input field, you can see that functionality in the demo: https://material.angular.io/components/select/examples

This seems like solid UI for a list that is 3 items in length, but working with a list that is 20+ items causes the list to shift drastically (selecting an option at the bottom of the list causes the entire list to move up to the point of covering other input fields above.

Top position

I am trying to find a way to have the select dropdown overlay be stationary (always below the input field itself). I have tried editing the _calculateOverlayPosition method on the prototype of the MdSelect class but I have not had much success. Has anyone run into this issue? Template and associated controller are very cookie cutter.

Template:

<md-select (change)="currencySelected()" formControlName="currency"
  <md-option *ngFor="let currency of currencies 
  [value]="currency.label">
  {{ currency.label }} - {{ currency.description }}
  </md-option>
</md-select>
1
Here is the bottom position: imgur.com/a/hRd16Sven E

1 Answers

1
votes

With the help of a coworker I managed to extend / edit the calculateOverlayPosition method via a custom util that gets utilized anytime MdOptionSelectionChange executes.

_mdSelect.prototype._calculateOverlayPosition = function() {
  const items = this._getItemCount();
  const panelHeight = Math.min(items * SELECT_ITEM_HEIGHT, 
  SELECT_PANEL_MAX_HEIGHT);
  const scrollContainerHeight = items * SELECT_ITEM_HEIGHT;

  // The farthest the panel can be scrolled before it hits the bottom
  const maxScroll = scrollContainerHeight - panelHeight;

  let groupLabels = countGroupLabelsBeforeOption(0, this.options, 
  this.optionGroups);

  this._offsetY = (SELECT_ITEM_HEIGHT - SELECT_TRIGGER_HEIGHT) / 2 * -1 - (groupLabels * SELECT_ITEM_HEIGHT);

  // Add 40 pixels to the y-axis to align dropdown below the input field
  this._offsetY = this._offsetY + 40;

  this._checkOverlayWithinViewport(maxScroll);
}