Skip to content

Commit

Permalink
Add support for number values with underscores
Browse files Browse the repository at this point in the history
- Aligns with JavaScript numeric separators - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#numeric_separators
- Example `data-wait-delay-value="7_000"`
- Closes hotwired#646
  • Loading branch information
LB Johnston committed Jun 20, 2023
1 parent eda0f9d commit 29437dd
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 27 deletions.
50 changes: 24 additions & 26 deletions docs/reference/values.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ You can read and write [HTML data attributes](https://developer.mozilla.org/en-U
<meta data-controller="callout" data-callout-text-value="data-loader-url-value=&quot;/messages&quot;">

```html
<div data-controller="loader"
data-loader-url-value="/messages">
</div>
<div data-controller="loader" data-loader-url-value="/messages"></div>
```

<meta data-controller="callout" data-callout-text-value="static values = { url: String }">
Expand All @@ -24,7 +22,7 @@ import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
static values = {
url: String
url: String,
}

connect() {
Expand All @@ -42,7 +40,7 @@ export default class extends Controller {
static values = {
url: String,
interval: Number,
params: Object
params: Object,
}

//
Expand All @@ -53,37 +51,37 @@ export default class extends Controller {

A value's type is one of `Array`, `Boolean`, `Number`, `Object`, or `String`. The type determines how the value is transcoded between JavaScript and HTML.

Type | Encoded as… | Decoded as…
---- | ----------- | -----------
Array | `JSON.stringify(array)` | `JSON.parse(value)`
Boolean | `boolean.toString()` | `!(value == "0" \|\| value == "false")`
Number | `number.toString()` | `Number(value)`
Object | `JSON.stringify(object)` | `JSON.parse(value)`
String | Itself | Itself
| Type | Encoded as… | Decoded as… |
| ------- | ------------------------ | --------------------------------------- |
| Array | `JSON.stringify(array)` | `JSON.parse(value)` |
| Boolean | `boolean.toString()` | `!(value == "0" \|\| value == "false")` |
| Number | `number.toString()` | `Number(value.replace(/_/g, ""))` |
| Object | `JSON.stringify(object)` | `JSON.parse(value)` |
| String | Itself | Itself |

## Properties and Attributes

Stimulus automatically generates getter, setter, and existential properties for each value defined in a controller. These properties are linked to data attributes on the controller's element:

Kind | Property name | Effect
---- | ------------- | ------
Getter | `this.[name]Value` | Reads `data-[identifier]-[name]-value`
Setter | `this.[name]Value=` | Writes `data-[identifier]-[name]-value`
Existential | `this.has[Name]Value` | Tests for `data-[identifier]-[name]-value`
| Kind | Property name | Effect |
| ----------- | --------------------- | ------------------------------------------ |
| Getter | `this.[name]Value` | Reads `data-[identifier]-[name]-value` |
| Setter | `this.[name]Value=` | Writes `data-[identifier]-[name]-value` |
| Existential | `this.has[Name]Value` | Tests for `data-[identifier]-[name]-value` |

### Getters

The getter for a value decodes the associated data attribute into an instance of the value's type.

If the data attribute is missing from the controller's element, the getter returns a _default value_, depending on the value's type:

Type | Default value
---- | -------------
Array | `[]`
Boolean | `false`
Number | `0`
Object | `{}`
String | `""`
| Type | Default value |
| ------- | ------------- |
| Array | `[]` |
| Boolean | `false` |
| Number | `0` |
| Object | `{}` |
| String | `""` |

### Setters

Expand Down Expand Up @@ -136,9 +134,9 @@ Values that have not been specified on the controller element can be set by defa
```js
export default class extends Controller {
static values = {
url: { type: String, default: '/bill' },
url: { type: String, default: "/bill" },
interval: { type: Number, default: 5 },
clicked: Boolean
clicked: Boolean,
}
}
```
Expand Down
2 changes: 1 addition & 1 deletion src/core/value_properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ const readers: { [type: string]: Reader } = {
},

number(value: string): number {
return Number(value)
return Number(value.replace(/_/g, ""))
},

object(value: string): object {
Expand Down
8 changes: 8 additions & 0 deletions src/tests/modules/core/value_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ export default class ValueTests extends ControllerTestCase(ValueController) {
this.controller.numericValue = "" as any
this.assert.equal(this.controller.numericValue, 0)
this.assert.equal(this.get("numeric-value"), "")

// Number values should support Numeric separators
this.set("numeric-value", "7_150")
this.assert.equal(this.controller.numericValue, 7150)

// Number values should be written simply, without Numeric separators
this.controller.numericValue = 10500
this.assert.deepEqual(this.get("numeric-value"), "10500")
}

"test boolean values"() {
Expand Down

0 comments on commit 29437dd

Please sign in to comment.