src/app/modules/content/stage-nav/stage-nav.component.ts
Component that allows the user to change the viewing angle and rendering mode of the stage.
changeDetection | ChangeDetectionStrategy.OnPush |
selector | ccf-stage-nav |
styleUrls | ./stage-nav.component.scss |
templateUrl | ./stage-nav.component.html |
Properties |
Methods |
Inputs |
Outputs |
HostBindings |
HostListeners |
Accessors |
constructor(ga: GoogleAnalyticsService)
|
||||||||
Creates an instance of stage nav component.
Parameters :
|
side | |
Type : Side
|
|
Default value : 'anterior'
|
|
Input that allows changing the current side from outside the component |
useDropdownMenu | |
Type : boolean
|
|
Whether to use a drop down menu instead of a options bar |
view3D | |
Type : boolean
|
|
Default value : false
|
|
Input that allows toggling of 3D view on / off from outside the component |
sideChange | |
Type : EventEmitter
|
|
Output that emits whenever the current side selection changes |
view3DChange | |
Type : EventEmitter
|
|
Output that emits whenever the 3D view is toggled on / off |
class |
Type : "ccf-stage-nav"
|
Default value : 'ccf-stage-nav'
|
HTML class name |
handleClick | ||||||||
handleClick(target: HTMLElement)
|
||||||||
Decorators :
@HostListener('document:click', ['$event.target'])
|
||||||||
Listens to document click event Closes the popup only if user clicks outside the popup
Parameters :
Returns :
void
|
updateSide | ||||||||
updateSide(selection: Side)
|
||||||||
Handles the updating of the side selection and calling the event emitter
Parameters :
Returns :
void
|
updateView | ||||||||
updateView(selection: boolean)
|
||||||||
Handles updating of the boolean that keeps track of current view and calling the event emitter.
Parameters :
Returns :
void
|
Readonly clsName |
Type : string
|
Default value : 'ccf-stage-nav'
|
Decorators :
@HostBinding('class')
|
HTML class name |
isDropdownActive |
Default value : false
|
Whether this component shows a dropdown menu or an options bar |
isDropdownHidden |
Default value : true
|
Whether the dropdown menu is hidden |
labelRef |
Type : ElementRef<HTMLElement>
|
Decorators :
@ViewChild('label', {static: true})
|
Label for dropdown |
optionsRef |
Type : ElementRef<HTMLElement>
|
Decorators :
@ViewChild('options', {static: true})
|
Options dropdown |
useDropdownMenu | ||||||
setuseDropdownMenu(value: boolean)
|
||||||
Whether to use a drop down menu instead of a options bar
Parameters :
Returns :
void
|
import {
ChangeDetectionStrategy,
Component,
ElementRef,
EventEmitter,
HostBinding,
HostListener,
Input,
Output,
ViewChild,
} from '@angular/core';
import { GoogleAnalyticsService } from 'ngx-google-analytics';
/** Valid values for side. */
export type Side = 'left' | 'right' | 'anterior' | 'posterior' | '3D';
/** Component that allows the user to change the viewing angle and rendering mode of the stage. */
@Component({
selector: 'ccf-stage-nav',
templateUrl: './stage-nav.component.html',
styleUrls: ['./stage-nav.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class StageNavComponent {
/** HTML class name */
@HostBinding('class') readonly clsName = 'ccf-stage-nav';
/** Whether to use a drop down menu instead of a options bar */
@Input()
set useDropdownMenu(value: boolean) {
this.isDropdownActive = value;
this.isDropdownHidden = true;
}
/** Input that allows changing the current side from outside the component */
@Input() side: Side = 'anterior';
/** Input that allows toggling of 3D view on / off from outside the component */
@Input() view3D = false;
/** Output that emits whenever the current side selection changes */
@Output() readonly sideChange = new EventEmitter<Side>();
/** Output that emits whenever the 3D view is toggled on / off */
@Output() readonly view3DChange = new EventEmitter<boolean>();
/** Label for dropdown */
@ViewChild('label', { static: true }) labelRef!: ElementRef<HTMLElement>;
/** Options dropdown */
@ViewChild('options', { static: true }) optionsRef!: ElementRef<HTMLElement>;
/** Whether this component shows a dropdown menu or an options bar */
isDropdownActive = false;
/** Whether the dropdown menu is hidden */
isDropdownHidden = true;
/** Simple helper for accessing the native label element */
private get labelEl(): HTMLElement {
return this.labelRef.nativeElement;
}
/** Simple helper for accessing the native options element */
private get optionsEl(): HTMLElement {
return this.optionsRef.nativeElement;
}
/**
* Creates an instance of stage nav component.
*
* @param ga Analytics service
*/
constructor(private readonly ga: GoogleAnalyticsService) {}
/**
* Listens to document click event
* Closes the popup only if user clicks outside the popup
*
* @param target The element on which the event was fired
*/
@HostListener('document:click', ['$event.target'])
handleClick(target: HTMLElement): void {
const { isDropdownHidden, labelEl, optionsEl } = this;
if (labelEl.contains(target)) {
this.isDropdownHidden = !isDropdownHidden;
} else if (!optionsEl.contains(target)) {
this.isDropdownHidden = true;
}
}
/**
* Handles the updating of the side selection and calling the event emitter
*
* @param selection the new selected side
*/
updateSide(selection: Side): void {
this.ga.event('side_update', 'stage_nav', selection);
if (selection === '3D') {
this.updateView(true);
} else {
this.updateView(false);
this.side = selection;
this.sideChange.emit(this.side);
}
}
/**
* Handles updating of the boolean that keeps track of current view
* and calling the event emitter.
*
* @param selection 3D (true) or Register (false)
*/
updateView(selection: boolean): void {
this.view3D = selection;
this.ga.event('view_update', 'stage_nav', selection ? '3D' : 'Register');
this.view3DChange.emit(this.view3D);
}
}
<div class="dropdown-label" [class.dropdown]="isDropdownActive" #label>
<mat-label>Options</mat-label>
<mat-icon>arrow_drop_down</mat-icon>
</div>
<div
class="stage-options"
[class.dropdowncontainer]="isDropdownActive"
[class.hidden]="isDropdownActive && isDropdownHidden"
#options
>
<mat-radio-group class="input-group" [value]="side" (change)="updateSide($event.value)">
<mat-radio-button value="left" class="nav-input">Left</mat-radio-button>
<mat-radio-button value="right" class="nav-input">Right</mat-radio-button>
<mat-radio-button value="anterior" class="nav-input" checked>Anterior</mat-radio-button>
<mat-radio-button value="posterior" class="nav-input">Posterior</mat-radio-button>
</mat-radio-group>
<ccf-labeled-slide-toggle
matTooltip="Change view."
class="view-slider"
[labels]="['Register', '3D\u00A0Preview']"
[value]="view3D ? '3D\u00A0Preview' : 'Register'"
(valueChange)="updateView($event !== 'Register')"
>
</ccf-labeled-slide-toggle>
</div>
./stage-nav.component.scss
:host {
display: flex;
flex-direction: column;
flex-wrap: wrap;
.dropdown-label {
display: none;
align-items: center;
mat-label,
mat-icon {
line-height: 1.5rem;
}
&.dropdown {
display: flex;
cursor: pointer;
align-items: start;
}
}
.stage-options {
display: flex;
align-items: center;
.input-group {
.nav-input {
margin-right: 1rem;
margin-bottom: 1.5rem;
}
mat-radio-button {
::ng-deep .mdc-label {
font-size: 1.25rem;
}
}
}
.view-slider {
white-space: nowrap;
display: flex;
::ng-deep .slider {
display: flex;
}
::ng-deep .slide-label {
font-size: 1.25rem;
}
}
&.dropdowncontainer {
display: flex;
flex-direction: column;
border-radius: 0.25rem;
position: absolute;
top: 3.5rem;
z-index: 11;
transition: opacity 0.25s;
:first-child {
margin-top: 0.5rem;
}
:last-child {
margin-bottom: 0.5rem;
}
.input-group {
margin-left: 0.875rem;
margin-right: 0;
display: flex;
flex-wrap: wrap;
.nav-input {
display: flex;
margin: 0;
margin-right: 0.875rem;
height: 2.5rem;
::ng-deep .mdc-label {
padding-left: 0;
}
}
}
.view-slider {
display: flex;
align-items: center;
height: 3rem;
margin: 0 0.5rem;
}
mat-divider {
visibility: visible;
border-top: 2px solid;
}
}
&.hidden {
visibility: hidden;
opacity: 0;
transition:
visibility 0.25s,
opacity 0.25s;
mat-divider {
visibility: hidden;
}
}
}
}