Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(VSlider): respect decimals from min #16667

Merged
merged 11 commits into from
Mar 19, 2023
Merged

Conversation

yuwu9145
Copy link
Member

fixes #16634

Description

fixes #16634

Markup:

<template>
  <v-app>
    <v-main>
      <v-slider v-model="currentValue" :min="min" :max="max" :step="step">
        <template class="pa-0" v-slot:prepend>
        <v-btn
          @click="sliderDecrement"
        >-</v-btn>
      </template>
      <template v-slot:append>
        <v-btn
          @click="sliderIncrement"
        >+</v-btn>
      </template>
      </v-slider>
      <p>
        Value: {{currentValue}}
      </p>
      <p>
  			<br>
        You can see here problem when using slider with initial value=1.001, step=1, max=10.001, min=1.001<br>
				Expected jumps would be 2.001, 3.001, 4.001...<br>
        But v-slider will round based on step decimals so the jumps will be 2, 3, 4..<br><br>
        Expected behavior is simulated on + and - buttons.<br><br>
				I copied your code for calculating values and made proposal fix for your rounding function.<br><br>
				The problem actually is how you are calculating number of 'decimals'.<br><br>
				My suggestion is to check decimals also for max and min and choose the biggest number.
      </p>
    </v-main>
  </v-app>
</template>

<script>
import { defineComponent } from "vue";
export default defineComponent({
  name: "App",
  data() {
    return {
      currentValue: 1.001,
      step: 1,
      min: 1.001,
      max: 10.001,
      decimals: 0
    };
  },
  mounted() {
    this.decimals = this.calculateDecimals();
  },
  methods: {
    calculateDecimals() {
      const trimmedStep = this.step.toString().trim();
      const trimmedMin = this.min.toString().trim();
      const trimmedMax = this.max.toString().trim();
      
      const stepDecimals = trimmedStep.includes(".")
        ? trimmedStep.length - trimmedStep.indexOf(".") - 1
        : 0;
      const minDecimals = trimmedMin.includes(".")
        ? trimmedMin.length - trimmedMin.indexOf(".") - 1
        : 0;
      const maxDecimals = trimmedMax.includes(".")
      ? trimmedMax.length - trimmedMax.indexOf(".") - 1
      : 0;
      
      return Math.max(stepDecimals, minDecimals, maxDecimals);
    },
    clamp(value, min = 0, max = 1) {
      return Math.max(min, Math.min(max, value));
    },
    roundValue(value) {
      const clamped = this.clamp(
        value,
        this.min,
        this.max
      );
      const offset = this.min % this.step;
      const newValue =
        Math.round((clamped - offset) / this.step) * this.step + offset;

      return parseFloat(
        Math.min(newValue, this.max).toFixed(this.decimals)
      );
    },
    sliderDecrement() {
      if (this.currentValue > this.min && this.step) {
        this.currentValue = this.roundValue(this.currentValue - this.step);
      }
    },
    sliderIncrement() {
      if (this.currentValue < this.max && this.step) {
        this.currentValue = this.roundValue(this.currentValue + this.step)
      }
    },
  }
});
</script>

@yuwu9145
Copy link
Member Author

in js, 3+1.001===4.0009999999999994.

Should we defined a default max decimals for this case? E.g. if maxDecimals=3, it will equal to 4.001

@johnleider
Copy link
Member

in js, 3+1.001===4.0009999999999994.

Should we defined a default max decimals for this case? E.g. if maxDecimals=3, it will equal to 4.001

Could @KaelWD or @nekosaur chime in on this?

@johnleider johnleider marked this pull request as draft February 15, 2023 15:57
@johnleider
Copy link
Member

This is still having issues with rounding.

@yuwu9145 yuwu9145 force-pushed the fix-16634 branch 2 times, most recently from c1d7561 to bddd8fa Compare February 16, 2023 11:31
@yuwu9145 yuwu9145 changed the title fix(VSlider): respect decimals in mouse move fix(VSlider): respect decimals from min Feb 16, 2023
@johnleider johnleider added T: bug Functionality that does not work as intended/expected C: VSlider VSlider labels Feb 16, 2023
@yuwu9145 yuwu9145 marked this pull request as ready for review February 17, 2023 09:29
@yuwu9145
Copy link
Member Author

yuwu9145 commented Feb 17, 2023

Solution has been refactored:

In rounding logic, decimals was used to be only calculated based on step, it should also consider the decimals from min

johnleider
johnleider previously approved these changes Feb 22, 2023
@johnleider johnleider requested a review from nekosaur February 22, 2023 15:23
@yuwu9145 yuwu9145 requested a review from nekosaur March 6, 2023 05:43
@KaelWD KaelWD self-requested a review March 8, 2023 14:06
@KaelWD KaelWD added this to the v3.1.x milestone Mar 19, 2023
@KaelWD KaelWD merged commit 13ba9d7 into vuetifyjs:master Mar 19, 2023
@yuwu9145 yuwu9145 deleted the fix-16634 branch March 19, 2023 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: VSlider VSlider T: bug Functionality that does not work as intended/expected
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug Report][3.1.4] v-slider step wrong rounding/decimals
4 participants