src/components/sq-input-range/sq-input-range.component.ts
Represents an input component for selecting a numeric value within a specified range.
This component allows users to input a numeric value within a defined range and provides visual feedback for the selected value.
<sq-input-range [name]='"input-range"' [(value)]='number' ></sq-input-range>
AfterContentInit
OnChanges
selector | sq-input-range |
styleUrls | ./sq-input-range.component.scss |
templateUrl | ./sq-input-range.component.html |
Properties |
|
Methods |
Inputs |
Outputs |
constructor(validatorHelper: ValidatorHelper, element: ElementRef, translate: TranslateService)
|
||||||||||||||||
Creates an instance of
Parameters :
|
color | |
Type : string
|
|
Default value : 'var(--primary_color)'
|
|
The color of the input component. |
customClass | |
Type : string
|
|
Default value : ''
|
|
A custom CSS class to apply to the input element. |
errorSpan | |
Type : boolean
|
|
Default value : true
|
|
Whether to display an error message below the input. |
externalError | |
Type : any
|
|
An external error message, if provided. |
id | |
Type : string
|
|
The id attribute for the input element. |
label | |
Type : string
|
|
Default value : ''
|
|
The label to display for the input. |
labelColor | |
Type : string
|
|
Default value : ''
|
|
The color of the input label. |
maxNumber | |
Type : number
|
|
Default value : 100
|
|
The maximum allowed value for the input. |
minNumber | |
Type : number
|
|
Default value : 0
|
|
The minimum allowed value for the input. |
name | |
Type : string
|
|
Default value : `random-name-${(1 + Date.now() + Math.random()).toString().replace('.', '')}`
|
|
The name attribute for the input element. |
readonly | |
Type : boolean
|
|
Default value : false
|
|
Whether the input is read-only. |
required | |
Type : boolean
|
|
Default value : false
|
|
Whether the input is required. |
step | |
Type : number
|
|
Default value : 1
|
|
The step value for the input. |
useFormErrors | |
Type : boolean
|
|
Default value : true
|
|
Whether to use form-level error messages. |
value | |
Type : any
|
|
Default value : '0'
|
|
The initial value of the input. |
emitFocus | |
Type : EventEmitter<Event>
|
|
Event emitter for focus input changes. |
inFocus | |
Type : EventEmitter<boolean>
|
|
Event emitter for focusing or blurring the input. |
valid | |
Type : EventEmitter<boolean>
|
|
Event emitter for indicating the validity of the input. |
valueChange | |
Type : EventEmitter<any>
|
|
Event emitter for changes in the input value. |
change | ||||||||
change(event: any)
|
||||||||
Handle input value changes.
Parameters :
Returns :
void
|
changeValuePosition |
changeValuePosition()
|
Changes the visual position of the input value based on the current value, minimum and maximum allowed values.
Returns :
void
|
Async ngAfterContentInit |
ngAfterContentInit()
|
Lifecycle hook that runs after content initialization. It sets a timeout to change the value position.
Returns :
any
|
ngOnChanges | ||||||||
ngOnChanges(changes: SimpleChanges)
|
||||||||
Lifecycle hook that runs when changes occur in the component's input properties. It recalculates the value position when value-related properties change.
Parameters :
Returns :
void
|
Async setError | ||||||||
setError(key: string)
|
||||||||
Set an error message based on a translation key.
Parameters :
Returns :
any
|
validate | ||||||||
validate(isBlur)
|
||||||||
Validates the input value.
Parameters :
Returns :
void
|
error |
Type : boolean | string
|
Default value : false
|
The error message associated with the input. |
input |
Type : ElementRef
|
Decorators :
@ViewChild('input')
|
A reference to the 'input' element in the component template. |
labelTemplate |
Type : TemplateRef<HTMLElement> | null
|
Default value : null
|
Decorators :
@ContentChild('labelTemplate')
|
Reference to a label template. |
nativeElement |
Type : ElementRef
|
A reference to the native element of the component. |
Public translate |
Type : TranslateService
|
Decorators :
@Optional()
|
- An optional instance of the `TranslateService` for internationalization.
|
Public validatorHelper |
Type : ValidatorHelper
|
- An instance of the `ValidatorHelper` service.
|
valueFloating |
Type : ElementRef
|
Decorators :
@ViewChild('valueFloating')
|
A reference to the 'valueFloating' element in the component template. |
import { AfterContentInit, Component, ContentChild, ElementRef, EventEmitter, Input, OnChanges, Optional, Output, SimpleChanges, TemplateRef, ViewChild } from '@angular/core'
import { TranslateService } from '@ngx-translate/core'
import { ValidatorHelper } from '../../helpers/validator.helper'
import { sleep } from '../../helpers/sleep.helper'
/**
* Represents an input component for selecting a numeric value within a specified range.
*
* This component allows users to input a numeric value within a defined range and provides visual feedback for the selected value.
*
* @implements {AfterContentInit}
* @implements {OnChanges}
*
* <br>
* <label for='id-exemple-range'>
* Example Input Range
* </label>
* <input
* class='range mb-3'
* name="name-exemple-range"
* id="id-exemple-range"
* type="range"
* ></input>
*
* @example
* <sq-input-range [name]='"input-range"' [(value)]='number' ></sq-input-range>
*/
@Component({
selector: 'sq-input-range',
templateUrl: './sq-input-range.component.html',
styleUrls: ['./sq-input-range.component.scss']
})
export class SqInputRangeComponent implements AfterContentInit, OnChanges {
/**
* A custom CSS class to apply to the input element.
*/
@Input() customClass = ''
/**
* The name attribute for the input element.
*
* @default 'random-name-[hash-random-code]'
*/
@Input() name = `random-name-${(1 + Date.now() + Math.random()).toString().replace('.', '')}`
/**
* The id attribute for the input element.
*/
@Input() id?: string
/**
* The initial value of the input.
*/
@Input() value: any = '0'
/**
* Whether the input is read-only.
*/
@Input() readonly = false
/**
* Whether the input is required.
*/
@Input() required = false
/**
* The label to display for the input.
*/
@Input() label = ''
/**
* The color of the input component.
*/
@Input() color = 'var(--primary_color)'
/**
* The color of the input label.
*/
@Input() labelColor = ''
/**
* Whether to display an error message below the input.
*/
@Input() errorSpan = true
/**
* An external error message, if provided.
*/
@Input() externalError?: any
/**
* The step value for the input.
*/
@Input() step = 1
/**
* The minimum allowed value for the input.
*/
@Input() minNumber = 0
/**
* The maximum allowed value for the input.
*/
@Input() maxNumber = 100
/**
* Whether to use form-level error messages.
*/
@Input() useFormErrors = true
/**
* Event emitter for changes in the input value.
*/
@Output() valueChange: EventEmitter<any> = new EventEmitter()
/**
* Event emitter for focusing or blurring the input.
*/
@Output() inFocus: EventEmitter<boolean> = new EventEmitter()
/**
* Event emitter for indicating the validity of the input.
*/
@Output() valid: EventEmitter<boolean> = new EventEmitter()
/**
* Event emitter for focus input changes.
*/
@Output() emitFocus: EventEmitter<Event> = new EventEmitter<Event>()
/**
* A reference to the 'valueFloating' element in the component template.
*/
@ViewChild('valueFloating') valueFloating!: ElementRef
/**
* A reference to the 'input' element in the component template.
*/
@ViewChild('input') input!: ElementRef
/**
* Reference to a label template.
*/
@ContentChild('labelTemplate')
labelTemplate: TemplateRef<HTMLElement> | null = null
/**
* The error message associated with the input.
*/
error: boolean | string = false
/**
* A reference to the native element of the component.
*/
nativeElement: ElementRef
/**
* Creates an instance of `SqInputRangeComponent`.
*
* @param validatorHelper - An instance of the `ValidatorHelper` service.
* @param element - A reference to the element hosting the component.
* @param translate - An optional instance of the `TranslateService` for internationalization.
*/
constructor(
public validatorHelper: ValidatorHelper,
element: ElementRef,
@Optional() public translate: TranslateService,
) {
this.nativeElement = element.nativeElement
}
/**
* Lifecycle hook that runs after content initialization.
* It sets a timeout to change the value position.
*/
async ngAfterContentInit() {
await sleep()
this.changeValuePosition()
}
/**
* Lifecycle hook that runs when changes occur in the component's input properties.
* It recalculates the value position when value-related properties change.
*
* @param changes - An object containing changes to input properties.
*/
ngOnChanges(changes: SimpleChanges) {
if (changes.hasOwnProperty('value') || changes.hasOwnProperty('minNumber') || changes.hasOwnProperty('maxNumber')) {
this.changeValuePosition()
}
}
/**
* Validates the input value.
*
* @param isBlur - Indicates whether the validation is triggered by blurring the input.
*/
validate(isBlur = false) {
if (this.externalError) {
this.error = false
} else if (!!this.required && !this.value && this.value !== '0') {
this.setError('forms.required')
this.valid.emit(false)
} else {
this.valid.emit(true)
this.error = ''
}
if (isBlur) {
this.inFocus.emit(false)
}
}
/**
* Changes the visual position of the input value based on the current value,
* minimum and maximum allowed values.
*/
changeValuePosition() {
const val = parseFloat(this.value)
const min = this.minNumber ? this.minNumber : 0
const max = this.maxNumber ? this.maxNumber : 100
const newVal = Number(((val - min) * 100) / (max - min))
if (this.valueFloating) {
this.valueFloating.nativeElement.style.left = `calc(${newVal}% + (${10 - newVal * 0.36}px))`
}
}
/**
* Handle input value changes.
* @param event - The input change event.
*/
change(event: any): void {
this.inFocus.emit(true)
this.changeValuePosition()
this.value = event
this.valueChange.emit(event)
this.validate()
}
/**
* Set an error message based on a translation key.
* @param key - The translation key for the error message.
*/
async setError(key: string) {
if (this.useFormErrors && this.translate) {
this.error = await this.translate.instant(key)
}
}
}
<div class="wrapper-all-inside-input {{ customClass }}" [ngClass]="{
'no-label': !label.length
}">
<label
class="display-flex"
*ngIf="label?.length || labelTemplate"
[ngClass]="{
readonly: readonly
}"
[for]="id"
>
<div *ngIf="label?.length && !labelTemplate" [ngStyle]="{ 'color': labelColor }" [innerHtml]="label | universalSafe"></div>
</label>
<div *ngIf="labelTemplate">
<ng-container *ngTemplateOutlet="labelTemplate"></ng-container>
</div>
<div
class="p-0 wrapper-input wrapper-input-squid"
[ngClass]="{
error: (externalError && externalError !== '') || (error && error !== ''),
}"
>
<output class="value-floating" #valueFloating>
{{ value }}
</output>
<input
[id]="id"
type="range"
class="range"
[name]="name"
[step]="step"
[required]="required"
[disabled]="readonly"
[min]="minNumber || ''"
[max]="maxNumber || ''"
(blur)="validate(true)"
[ngModel]="value"
(ngModelChange)="change($event)"
(focus)="emitFocus.emit()"
ngDefaultControl
#input
/>
</div>
<div class="box-validation box-invalid show" *ngIf="errorSpan">
<i [ngClass]="{
'visibility-hidden-force': !error && !externalError
}" class="fa-solid fa-triangle-exclamation"></i>
{{ externalError ? externalError : '' }}
{{ error && !externalError ? error : '' }}
</div>
</div>
./sq-input-range.component.scss
.wrapper-all-inside-input {
position: relative;
&.no-label{
margin-top: 2rem;
}
label {
margin: 0 auto 2.5rem;
}
input[type='range'] {
border-radius: 12px;
}
.value-floating {
position: absolute;
bottom: 26px;
font-size: 0.86rem;
line-height: 1;
left: 10px;
}
.box-validation {
margin-top: 0.5rem;
}
.wrapper-input.wrapper-input-squid {
position: relative;
}
}