src/app/shared/components/dropdown/dropdown.component.ts
Component for a dropdown menu.
changeDetection | ChangeDetectionStrategy.OnPush |
selector | ccf-dropdown |
styleUrls | ./dropdown.component.scss |
templateUrl | ./dropdown.component.html |
Properties |
Methods |
Inputs |
Outputs |
constructor(ga: GoogleAnalyticsService)
|
||||||||
Creates an instance of dropdown component.
Parameters :
|
label | |
Type : string
|
|
What the component is selecting for. |
options | |
Type : string[]
|
|
Choices displayed in the dropdown menu. |
selection | |
Type : string
|
|
Current option selected. |
selectionChange | |
Type : EventEmitter
|
|
Emits the new selected option when selection is changed. |
selectionChanged | ||||||||
selectionChanged(value: string)
|
||||||||
Updates the selected value.
Parameters :
Returns :
void
|
toggleOptions |
toggleOptions()
|
Controls fade-in effect after dropdown menu opens
Returns :
void
|
optionsVisible |
Type : string
|
Default value : 'invisible'
|
Determines if menu contents are visible (used for fade-in effect). |
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { GoogleAnalyticsService } from 'ngx-google-analytics';
/**
* Component for a dropdown menu.
*/
@Component({
selector: 'ccf-dropdown',
templateUrl: './dropdown.component.html',
styleUrls: ['./dropdown.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DropdownComponent {
/**
* What the component is selecting for.
*/
@Input() label!: string;
/**
* Choices displayed in the dropdown menu.
*/
@Input() options!: string[];
/**
* Current option selected.
*/
@Input() selection!: string;
/**
* Emits the new selected option when selection is changed.
*/
@Output() readonly selectionChange = new EventEmitter<string>();
/**
* Determines if menu contents are visible (used for fade-in effect).
*/
optionsVisible = 'invisible';
/**
* Creates an instance of dropdown component.
*
* @param ga Analytics service
*/
constructor(private readonly ga: GoogleAnalyticsService) {}
/**
* Controls fade-in effect after dropdown menu opens
*/
toggleOptions(): void {
this.optionsVisible = this.optionsVisible === 'visible' ? 'invisible' : 'visible';
}
/**
* Updates the selected value.
*
* @param value The value that has been selected
*/
selectionChanged(value: string): void {
this.selection = value;
this.ga.event('selection_change', 'dropdown', `${this.label}:${value}`);
this.selectionChange.emit(value);
}
}
<div class="ccf-dropdown wrapper">
<mat-form-field class="dropdown-form-field" subscriptSizing="dynamic">
<div class="label">
{{ label }}
</div>
<mat-select
class="selected-value"
[value]="selection"
(selectionChange)="selectionChanged($event.value)"
disableOptionCentering="true"
panelClass="option-panel"
(openedChange)="toggleOptions()"
disableRipple="true"
hideSingleSelectionIndicator="true"
>
<mat-option *ngFor="let option of options" [value]="option">
<div class="{{ optionsVisible }}">
{{ option }}
</div>
</mat-option>
</mat-select>
</mat-form-field>
</div>
./dropdown.component.scss
@keyframes slideInHorizontalDropdown {
from {
width: 0;
}
to {
width: 9.85rem;
}
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.dropdown-form-field {
width: 100%;
height: 3rem;
::ng-deep .mat-mdc-text-field-wrapper {
padding-left: 0.25rem;
padding-right: 0.25rem;
.mat-mdc-form-field-flex {
.mat-mdc-form-field-infix {
font-size: 0.875rem;
border: none;
.label {
height: 19.25px;
}
mat-select {
font-size: 1rem;
font-weight: bold;
.mat-mdc-select-arrow-wrapper {
position: relative;
bottom: 0.25rem;
right: 0.25rem;
}
}
}
}
.mdc-line-ripple::before {
border-bottom-width: 2px;
}
}
}
.visible {
animation: fadeIn 0.3s;
transition-delay: 0.275s;
animation-delay: 0.275s;
}
.invisible {
opacity: 0;
}
::ng-deep .option-panel {
animation: slideInHorizontalDropdown 0.3s;
animation-fill-mode: forwards;
flex-grow: 1;
padding: 0 !important;
mat-option {
border-bottom-width: 1px;
border-bottom-style: solid;
padding-left: 1em;
font-size: 16px;
}
:last-child {
border-bottom: none;
}
}
::ng-deep .cdk-overlay-pane {
min-width: 0rem !important;
}
::ng-deep .ccf-dropdown {
.mat-select-arrow-wrapper {
transform: translatey(-0.5em);
}
}