Last active
April 19, 2018 14:09
-
-
Save calebergh/899623183886f0460b134e80e1b42ecc to your computer and use it in GitHub Desktop.
Fancy Select / Dropdown for Angular
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ng-container(*ngIf="via_relay") | |
ng-template(#loading="") | |
p.loading.loading-xs.text-left | |
i.fas.fa-sync-alt.fa-spin | |
| Loading... | |
div.dropdown(*ngIf="relay_zones | async; else loading; let relay_zones", tabindex="0", (keyup)="handleKeyup($event, relay_zones)") | |
input(type="hidden", name="relay_zone", value="", [formControl]="ciscoForm.controls['relay_zone']") | |
.selected((click)="endpointRelayOpen = !endpointRelayOpen") | |
span.status(*ngIf="selectedRelay?.status", [connectionStatus]="selectedRelay.status") | |
span {{selectedRelay.name}} | |
.dropdown-options(*ngIf="endpointRelayOpen") | |
.dropdown-option(*ngFor="let relay of relays.data", (click)="setSelectedRelay(relay); endpointRelayOpen=false;", [class.active]="selectedRelay.id == relay.id") | |
i.far.fa-eye | |
| {{relay.name}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$light-grey: #ccc; | |
$dark-grey: #888; | |
// this is a SCSS placeholder, and is only included if it is extended | |
%fa-custom { | |
// extending this will require setting something like content: $fa-var-caret-down; | |
font-family: "Font Awesome\ 5 Free"; | |
/* default to 900 (free solid), other valid options are 400 (free regular and regular brands) */ | |
font-weight: 900; | |
-webkit-font-smoothing: antialiased; | |
} | |
.dropdown { | |
max-width: 250px; | |
position: relative; | |
cursor: pointer; | |
.selected { | |
border: 1px solid $dark-grey; | |
padding: 3px 25px 3px 5px; | |
overflow: hidden; | |
width: 100%; | |
box-sizing: border-box; | |
&:after { | |
@extend %fa-custom; | |
// relies on FontAwesome 5 Angular module | |
content: fa-content($fa-var-caret-down); | |
display: inline-block; | |
position: absolute; | |
top: 0; | |
right: 0; | |
padding: 6px 8px; | |
border-left: 1px solid $light-grey; | |
} | |
} | |
.dropdown-options { | |
position: absolute; | |
top: 25px; | |
z-index: 255555; | |
border: 1px solid $light-grey; | |
box-shadow: 2px 2px 4px $light-grey; | |
background: white; | |
box-sizing: border-box; | |
width: 100%; | |
} | |
.dropdown-option { | |
padding: 3px 5px; | |
& + .dropdown-option { | |
border-top: 1px solid $light-grey | |
} | |
&.active, | |
&:hover { | |
background: $lighter-grey; | |
} | |
i.far { | |
margin-right: 4px; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as _ from 'lodash'; | |
import {Component, OnInit, OnDestroy} from '@angular/core'; | |
import {FormBuilder, FormGroup, Validators} from '@angular/forms'; | |
import {Observable} from 'rxjs'; | |
@Component({ | |
selector: 'my-form', | |
template: require('./form.pug') | |
}) | |
export class FormComponent implements OnInit, OnDestroy { | |
private endpoint: any; | |
private relay_zones: Observable<any>; | |
private endpointRelayOpen: boolean = false; | |
setEndpointFormValue(formName: string, values: object) { | |
this[formName].patchValue(values); | |
} | |
setSelectedRelay(relay: IRelay) { | |
this.selectedRelay = relay; | |
this.setEndpointFormValue('ciscoForm', {relay_zone: relay.id}); | |
} | |
/** | |
* Accessibility for custom Dropdown (for relays) | |
* @param {*} $event | |
* @param {*} records | |
*/ | |
handleKeyup($event: any, records: any) { | |
// it appears that angular passes strings representing the keycodes, rather than numbers. nice. | |
// tab only fires when dropdown _receives_ focus, not when blurring. Causes issues, so stop here | |
if ('Tab' === $event.code) { | |
return; | |
} | |
// passed-in records are the full subscription response, attempt to drill into the "data" portion | |
records = _.get(records, 'data', records); | |
// space and enter will open / close the dropdown | |
if ('Space' === $event.code || 'Enter' === $event.code) { | |
this.endpointRelayOpen = !this.endpointRelayOpen; | |
return; | |
} | |
let currentIndex = _.findIndex(records, {id: _.get(this.selectedRelay, 'id')}); | |
// move up / down with the arrow keys | |
if ('ArrowDown' === $event.code) { | |
currentIndex += 1; | |
} else if ('ArrowUp' === $event.code) { | |
currentIndex -= 1; | |
} | |
// ensure within range. provide "wrapping" off the end / beginning | |
if (currentIndex < 0) { | |
currentIndex = (records.length - 1); | |
} else if (currentIndex >= records.length) { | |
currentIndex = 0; | |
} | |
this.setSelectedRelay(records[currentIndex]); | |
} | |
ngOnInit() { | |
this.relay_zones = this.API.getObservable('RelayZones'); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment