Why is Stimulus reading passed number values as strings instead of numbers?

102 views Asked by At

I'm having an issue where I'm trying to pass number values from HTML (liquid) to Stimulus, but Stimulus is reading them as strings why is this happening?

The values are being pulled from an API, the relevant JSON looks like this:

{
  "min": 1,
  "max": 5,
  "value": 3,
}

I'm passing value, max, and min to my input component's controller like so:

<input type="text"
           id="{{ id }}"
           name="{{ id }}"
           min="{{ min }}"
           max="{{ max }}"
           value="{{ value }}"
           pattern="\d*"
           data-selector-target="selector"
           data-selector-value="{{ value }}"
           data-selector-min="{{ min }}"
           data-selector-max="{{ max }}"
           class="selector p-1 w-9 text-center">

And I'm reading the values within my controller. If I console log the values, like in test() below:

import { Controller } from "@hotwired/stimulus";

export default class extends Controller {

  static targets = ['selector'];
  static values = {
    value: Number,
    min: Number,
    max: Number
  }

  test() {

    console.log({
      value: this.selectorTarget.value,
      typeofvalue: typeof(this.selectorTarget.value),
      min: this.selectorTarget.min,
      typeofmin: typeof(this.selectorTarget.min),
      max: this.selectorTarget.max,
      typeofmax: typeof(this.selectorTarget.max)})

  }

}

I get the following results in my console:

​value: "3"
typeofValue: "string"
min: "1"
typeofMin: "string"
max: "5"
typeofMax: "string"
​

Does anyone know why that's happening?

Thanks!

2

There are 2 answers

4
The Rock On

It is because you typed your <input> to text.

If you want it to consider the values as Numbers, then you have to type it so.

<input type="number">
0
Fracsi On

Accessing the attributes you want (min, max, value) on the HTMLInputElement are always returned as string. See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement

The selectorTarget is a simple HTMLInputElement (according to your HTML and JS code). There is nothing StimulusJS can do about it.

data-selector-*-value attributes are to be defined on the controller element. See: https://stimulus.hotwired.dev/reference/values

If you want to access the min, max and value from the Controller, add the values to the controller element. E.g:

<div data-controller="selector"
     data-selector-value="{{ value }}"
     data-selector-min="{{ min }}"
     data-selector-max="{{ max }}">
<input type="text"
           id="{{ id }}"
           name="{{ id }}"
           min="{{ min }}"
           max="{{ max }}"
           value="{{ value }}"
           pattern="\d*"
           data-selector-target="selector"
           class="selector p-1 w-9 text-center">
</div>
import { Controller } from "@hotwired/stimulus";

export default class extends Controller {

  static targets = ['selector'];
  static values = {
    value: Number,
    min: Number,
    max: Number
  }

  test() {

    console.log({
      value: this.valueValue,
      typeofvalue: typeof(this.valueValue),
      min: this.minValue,
      typeofmin: typeof(this.minValue),
      max: this.maxValue,
      typeofmax: typeof(this.maxValue)})

  }

}

Or you can use the Controller on you input element:

import { Controller } from "@hotwired/stimulus";

export default class extends Controller {

  static values = {
    value: Number,
    min: Number,
    max: Number
  }

  test() {

    console.log({
      value: this.valueValue,
      typeofvalue: typeof(this.valueValue),
      min: this.minValue,
      typeofmin: typeof(this.minValue),
      max: this.maxValue,
      typeofmax: typeof(this.maxValue)})

  }

}
<input type="text"
           id="{{ id }}"
           name="{{ id }}"
           min="{{ min }}"
           max="{{ max }}"
           value="{{ value }}"
           pattern="\d*"
           data-controller="selector"
           data-selector-value="{{ value }}"
           data-selector-min="{{ min }}"
           data-selector-max="{{ max }}"
           class="selector p-1 w-9 text-center">