2

I've created a range slider in a form in Angular which is used to record values and display recorded values.

<input [formControlName]="object.id" [id]="object.id" type="range" [(ngModel)]="object.answer" [step]="object.step" [min]="object.minValue" [max]="object.maxValue">

With object containing key-value pairs for id, answer, step, min, max which comes from database.

For following object,

{ id: 1, answer: 4, step: 0.25, minValue: 3, maxValue: 4 }

slider is displaying correct value, i.e., 4.

However, with answer: 3.25 and answer: 3.75, it is displaying 3 and 4 resp. Slider seems to be rounding off decimal answer values to nearest integer.

I looked up MDN for input range and under the step section, there was a note which said:

When the data entered by the user doesn't adhere to the stepping configuration, the user agent may round to the nearest valid value, preferring numbers in the positive direction when there are two equally close options.

But, aren't 3.25 or 3.75 valid values? Both can be written as (min + multiple of step) <= max for given min: 3, max: 4 and step: 0.25

I also looked up how to disable user-agent validation here and used novalidate attribute in form tag and slider was still not displaying correctly for decimal values. But, it displays correctly for integer values in specified range.

Edit 1: I tried checking with different types of 'step' values. It is displaying correctly for integer steps (1, 2, 3), decimal > 1 steps (1.1, 1.5, 2.5). It seems to be not displaying correctly with decimal < 1 steps (0.5, 0.3).

Edit 2: Also, if I use step="0.25" instead of [step]="object.step", it's displaying correctly. So, static step is working, but property bind-ed step value is not working properly and that too for step values < 1.

apooravc
  • 23
  • 5

1 Answers1

3

Live Example
I've tried to replicate your scenario with little tweaking and it seems to be working fine. Please have a look if it help you. Feel free to tweak the model values of obj as per your requirements.

Template:

<hello name="{{ name }}"></hello>
<p>
    Start editing to see some magic happen :)
  <br>Please see the console :)
</p>
<input 
[id]="obj.id" type="range" 
[step]="obj.step" [min]="obj.minValue" [max]="obj.maxValue" [(ngModel)]="obj.answer" 
 (ngModelChange)="valueChanged($event)"
>

Component:

import { Component, VERSION, OnChanges } from "@angular/core";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  name = "Angular " + VERSION.major;
  obj = {
    id: 1,
    answer: 0,
    step: 0.25,
    minValue: 0,
    maxValue: 47.8
  };
  constructor() {}

  valueChanged(event:any){
    console.log(event);
    console.log(this.obj);
  }
}
  • Your initial code didn't work for me, but your use of `(ngModelChange)` led me to split: `[(ngModel)]` into `[value]` and `(ngModelChange)` and after doing a bit more digging regarding order of min, max, step, value, following worked for me: `` – apooravc Sep 03 '20 at 15:19