diff --git a/projects/kit/components/input-range/input-range.component.ts b/projects/kit/components/input-range/input-range.component.ts index 11406f8cf866..69fdc8775704 100644 --- a/projects/kit/components/input-range/input-range.component.ts +++ b/projects/kit/components/input-range/input-range.component.ts @@ -93,6 +93,8 @@ export class TuiInputRangeComponent @Input() pluralize: Record | null = null; + leftTextfieldValue = this.safeCurrentValue[0]; + rightTextfieldValue = this.safeCurrentValue[1]; lastActiveSide: 'left' | 'right' = 'left'; constructor( @@ -178,17 +180,9 @@ export class TuiInputRangeComponent this.updateFocused(active); } - onTextInputFocused(focused: boolean, right: boolean): void { - if (focused) { - return; - } - - const [leftTextInputRef, rightTextInputRef] = this.inputNumberRefs; - const inputRef = right ? rightTextInputRef : leftTextInputRef; - const valueIndex = right ? 1 : 0; - - if (!inputRef.nativeValue || inputRef.value !== this.value[valueIndex]) { - this.updateTextInputValue(this.safeCurrentValue[valueIndex], right); + onTextInputFocused(focused: boolean): void { + if (!focused) { + this.updateTextfieldValues(this.value); } } @@ -206,15 +200,9 @@ export class TuiInputRangeComponent this.value[0] + leftCoefficient * this.step, this.value[1] + rightCoefficient * this.step, ]); - const leftValueChanged = newValue[0] !== this.value[0]; - const rightValueChanged = newValue[1] !== this.value[1]; - - if (leftValueChanged || rightValueChanged) { - this.safelyUpdateValue(newValue); - this.updateTextInputValue( - newValue[rightValueChanged ? 1 : 0], - rightValueChanged, - ); + + if (newValue[0] !== this.value[0] || newValue[1] !== this.value[1]) { + this.onExternalValueUpdate(newValue); } } @@ -226,15 +214,9 @@ export class TuiInputRangeComponent this.safelyUpdateValue([this.value[0], value ?? this.safeCurrentValue[1]]); } - onRangeValue(value: [number, number]): void { + onExternalValueUpdate(value: [number, number]): void { this.safelyUpdateValue(value); - - const rightValueChanged = this.lastActiveSide === 'right'; - - this.updateTextInputValue( - this.value[rightValueChanged ? 1 : 0], - rightValueChanged, - ); + this.updateTextfieldValues(this.value); } focusToTextInput(): void { @@ -252,6 +234,11 @@ export class TuiInputRangeComponent this.lastActiveSide = activeThumb; } + override writeValue(value: [number, number]): void { + super.writeValue(value); + this.updateTextfieldValues(this.value); + } + protected getFallbackValue(): [number, number] { return [0, 0]; } @@ -279,10 +266,8 @@ export class TuiInputRangeComponent return tuiClamp(roundedValue, this.min, this.max); } - private updateTextInputValue(value: number, right: boolean): void { - const [leftInputRef, rightInputRef] = this.inputNumberRefs; - const textInputRef = right ? rightInputRef : leftInputRef; - - textInputRef?.writeValue(value); + private updateTextfieldValues([leftValue, rightValue]: [number, number]): void { + this.leftTextfieldValue = leftValue; + this.rightTextfieldValue = rightValue; } } diff --git a/projects/kit/components/input-range/input-range.template.html b/projects/kit/components/input-range/input-range.template.html index 8fd37231184c..3d347ce0c144 100644 --- a/projects/kit/components/input-range/input-range.template.html +++ b/projects/kit/components/input-range/input-range.template.html @@ -17,11 +17,11 @@ [disabled]="computedDisabled" [max]="value[1]" [min]="min" - [ngModel]="value[0]" [precision]="precision" [readOnly]="readOnly" [tuiTextfieldPostfix]="pluralize && !showLeftValueContent ? (value[0] | i18nPlural: pluralize) : ''" - (focusedChange)="onTextInputFocused($event, false)" + [(ngModel)]="leftTextfieldValue" + (focusedChange)="onTextInputFocused($event)" (keydown.arrowDown)="changeByStep($event, [-1, 0])" (keydown.arrowUp)="changeByStep($event, [1, 0])" (ngModelChange)="onInputLeft($event)" @@ -45,11 +45,11 @@ [disabled]="computedDisabled" [max]="max" [min]="value[0]" - [ngModel]="value[1]" [precision]="precision" [readOnly]="readOnly" [tuiTextfieldPostfix]="pluralize && !showRightValueContent ? (value[1] | i18nPlural: pluralize) : ''" - (focusedChange)="onTextInputFocused($event, true)" + [(ngModel)]="rightTextfieldValue" + (focusedChange)="onTextInputFocused($event)" (keydown.arrowDown)="changeByStep($event, [0, -1])" (keydown.arrowUp)="changeByStep($event, [0, 1])" (ngModelChange)="onInputRight($event)" @@ -75,7 +75,7 @@ [segments]="segments" [step]="step" (activeThumbChange)="onActiveThumbChange($event)" - (ngModelChange)="onRangeValue($event)" + (ngModelChange)="onExternalValueUpdate($event)" (tuiPressedChange)="focusToTextInput()" > diff --git a/projects/kit/components/input-range/test/input-range.component.spec.ts b/projects/kit/components/input-range/test/input-range.component.spec.ts index 7cfc2fd25e98..26b64077340c 100644 --- a/projects/kit/components/input-range/test/input-range.component.spec.ts +++ b/projects/kit/components/input-range/test/input-range.component.spec.ts @@ -149,6 +149,18 @@ describe(`InputRange`, () => { expect(inputPORight.value).toBe(`5 лет`); }); + + it(`does not rounds to nearest multiple of [quantum] until text field losses focus`, () => { + inputPORight.sendText(`8`); + + expect(inputPORight.value).toBe(`8 лет`); + expect(testComponent.control.value[1]).toBe(10); + + inputPORight.blur(); + + expect(inputPORight.value).toBe(`10 лет`); + expect(testComponent.control.value[1]).toBe(10); + }); }); describe(`Deleting Values`, () => { @@ -197,6 +209,14 @@ describe(`InputRange`, () => { .replace(CHAR_HYPHEN, CHAR_MINUS)} лет`, ); }); + + it(`programmatic FormControl updates should also update textfield value`, async () => { + testComponent.control.patchValue([5, 10]); + await fixture.whenStable(); + + expect(inputPOLeft.value).toBe(`5 лет`); + expect(inputPORight.value).toBe(`10 лет`); + }); }); describe(`Format`, () => {