src/app/shared/components/slices-input/slices-input.component.ts
Component for entering data on block slices
changeDetection | ChangeDetectionStrategy.OnPush |
selector | ccf-slices-input |
styleUrls | ./slices-input.component.scss |
templateUrl | ./slices-input.component.html |
Properties |
|
Methods |
Inputs |
Outputs |
HostBindings |
Accessors |
constructor(ga: GoogleAnalyticsService)
|
||||||||
Creates an instance of slices input component.
Parameters :
|
slicesConfig | |
Type : SlicesConfig
|
|
Default value : DEFAULT_SLICES_CONFIG
|
|
Values of block dimensions to be emitted |
slicesConfigChange | |
Type : EventEmitter
|
|
Emitter for slice data values |
class |
Type : "ccf-slices-input"
|
Default value : 'ccf-slices-input'
|
HTML class name |
refreshSlices |
refreshSlices()
|
Refreshes all slice data values to empty values
Returns :
void
|
updateSlicesData | ||||||||||||
updateSlicesData(input: KeyboardEvent, key: string)
|
||||||||||||
Limits the length of the input if needed and updates values when an input changes
Parameters :
Returns :
void
|
Readonly clsName |
Type : string
|
Default value : 'ccf-slices-input'
|
Decorators :
@HostBinding('class')
|
HTML class name |
hasThicknessValue |
gethasThicknessValue()
|
Returns whether a valid thickness value has been entered.
Returns :
boolean
|
import { ChangeDetectionStrategy, Component, EventEmitter, HostBinding, Input, Output } from '@angular/core';
import { GoogleAnalyticsService } from 'ngx-google-analytics';
/**
* Interface containing slices data of the tissue block
*/
export interface SlicesConfig {
/** Thickness of each tissue slice */
thickness: number;
/** Number of slices in the block */
numSlices: number;
}
/** Default values for slices config. */
const DEFAULT_SLICES_CONFIG: SlicesConfig = {
thickness: NaN,
numSlices: NaN,
};
/**
* Component for entering data on block slices
*/
@Component({
selector: 'ccf-slices-input',
templateUrl: './slices-input.component.html',
styleUrls: ['./slices-input.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SlicesInputComponent {
/** HTML class name */
@HostBinding('class') readonly clsName = 'ccf-slices-input';
/**
* Values of block dimensions to be emitted
*/
@Input() slicesConfig = DEFAULT_SLICES_CONFIG;
/**
* Emitter for slice data values
*/
@Output() readonly slicesConfigChange = new EventEmitter<SlicesConfig>();
/**
* Returns whether a valid thickness value has been entered.
*/
get hasThicknessValue(): boolean {
return !isNaN(this.slicesConfig.thickness);
}
/**
* Creates an instance of slices input component.
*
* @param ga Analytics service
*/
constructor(private readonly ga: GoogleAnalyticsService) {}
/**
* Limits the length of the input if needed and updates values when an input changes
*
* @param input Event from the input element which contains the new value
* @param key Name of the dimension to be updated
*/
updateSlicesData(input: KeyboardEvent, key: string): void {
const { value: strValue } = input.target as HTMLInputElement;
this.slicesConfig = { ...this.slicesConfig, [key]: strValue !== '' ? +strValue : NaN };
this.ga.event('slice_config_update', 'slice_input', key, this.slicesConfig[key as never]);
this.slicesConfigChange.emit(this.slicesConfig);
}
/**
* Refreshes all slice data values to empty values
*/
refreshSlices(): void {
this.slicesConfig = DEFAULT_SLICES_CONFIG;
this.ga.event('slice_config_reset', 'slice_input');
this.slicesConfigChange.emit(this.slicesConfig);
}
}
<div class="header">
<span class="text title" matTooltip="Add thickness of tissue sections and the total number of sections"
>Tissue Sections</span
>
<div class="filler"></div>
<mat-icon
matRipple
[matRippleCentered]="true"
[matRippleUnbounded]="true"
class="icon refresh"
(click)="refreshSlices()"
>
refresh
</mat-icon>
</div>
<div class="slices-inputs">
<mat-form-field class="field">
<mat-label class="text form-input-label">Thickness</mat-label>
<input
matInput
ccfNumbersOnly
class="input"
type="number"
[value]="slicesConfig.thickness"
(keyup)="updateSlicesData($event, 'thickness')"
matTooltip="Enter thickness of tissue sections"
/>
<div matSuffix class="suffix" [class.show]="hasThicknessValue">μm</div>
</mat-form-field>
<mat-form-field class="field">
<mat-label class="text form-input-label"># Sections</mat-label>
<input
matInput
ccfNumbersOnly
class="input"
type="number"
[value]="slicesConfig.numSlices"
(keyup)="updateSlicesData($event, 'numSlices')"
matTooltip="Enter total number of sections"
/>
</mat-form-field>
</div>
./slices-input.component.scss
:host {
display: flex;
flex-direction: column;
gap: 0.5rem;
input[type='number'] {
-moz-appearance: textfield;
}
.header {
display: flex;
align-items: center;
height: 1.5rem;
padding: 0.5rem 0;
.title {
font-weight: 400;
}
.refresh {
transform: scaleX(-1);
cursor: pointer;
transition: 0.6s;
&:hover {
border-radius: 2px;
}
}
}
.slices-inputs {
display: flex;
justify-content: space-between;
width: 20rem;
margin: 0 auto;
.field {
width: 9rem;
&:not(:last-child) {
padding-right: 0.75rem;
}
.input {
text-align: center;
}
.suffix {
display: none;
}
&.mat-focused .suffix,
.suffix.show {
display: initial;
}
::ng-deep .mdc-text-field {
padding: 0;
.mat-mdc-form-field-infix {
padding-bottom: 0;
min-height: inherit;
}
.mat-mdc-form-field-icon-suffix {
padding: 1.5rem 0 0 0;
}
}
}
}
.filler {
flex-grow: 1;
}
}