Add wildcard support (#805)
* Dispatch `datastar-sse` event on `document` * Release note * Fix * Modify view transition * Fixes * Fixes * Add wildcard support * Add wildcard to OnSignalChange
This commit is contained in:
parent
05c751770b
commit
5ba9759fba
|
@ -16,4 +16,7 @@ Each tagged version of Datastar is accompanied by a release note. Read the [rele
|
|||
|
||||
### Changed
|
||||
|
||||
- The `datastar-sse` event is now dispatched on the `document` element, and using `data-on-datastar-sse` automatically listens for the event on the `document` ([#802](https://github.com/starfederation/datastar/issues/802)).
|
||||
- The `datastar-sse` event is now dispatched on the `document` element, and using `data-on-datastar-sse` automatically listens for the event on the `document` ([#802](https://github.com/starfederation/datastar/issues/802)).
|
||||
- The `data-on-signals-change-*` attribute key now accepts a path in which `*` can be used as a wildcard (`data-on-signals-change-foo.*`).
|
||||
- The `@setAll` action now accepts one or more space-separated paths in which `*` can be used as a wildcard (`@setAll('foo.* bar.*', true)`).
|
||||
- The `@toggleAll` action now accepts one or more space-separated paths in which `*` can be used as a wildcard (`@toggleAll('foo.* bar.*', true)`).
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
Datastar helps you build reactive web applications with the simplicity of server-side rendering and the power of a full-stack SPA framework.
|
||||
|
||||
Getting started is as easy as adding a single 14.5 KiB script tag to your HTML.
|
||||
Getting started is as easy as adding a single 14.6 KiB script tag to your HTML.
|
||||
|
||||
```html
|
||||
<script type="module" src="https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-beta.10/bundles/datastar.js"></script>
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -10,7 +10,7 @@
|
|||
|
||||
Datastar helps you build reactive web applications with the simplicity of server-side rendering and the power of a full-stack SPA framework.
|
||||
|
||||
Getting started is as easy as adding a single 14.5 KiB script tag to your HTML.
|
||||
Getting started is as easy as adding a single 14.6 KiB script tag to your HTML.
|
||||
|
||||
```html
|
||||
<script type="module" src="https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-beta.10/bundles/datastar.js"></script>
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
PluginType,
|
||||
Requirement,
|
||||
} from '../../../../engine/types'
|
||||
import { pathMatchesPattern } from '../../../../utils/paths'
|
||||
import { modifyCasing } from '../../../../utils/text'
|
||||
import { modifyTiming } from '../../../../utils/timing'
|
||||
import { modifyViewTransition } from '../../../../utils/view-transtions'
|
||||
|
@ -33,10 +34,10 @@ export const OnSignalChange: AttributePlugin = {
|
|||
}
|
||||
}
|
||||
|
||||
const signalPath = modifyCasing(key, mods)
|
||||
const pattern = modifyCasing(key, mods)
|
||||
const signalValues = new Map<Signal, any>()
|
||||
signals.walk((path, signal) => {
|
||||
if (path.startsWith(signalPath)) {
|
||||
if (pathMatchesPattern(path, pattern)) {
|
||||
signalValues.set(signal, signal.value)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,16 +1,25 @@
|
|||
// Authors: Delaney Gillilan
|
||||
// Icon: ion:checkmark-round
|
||||
// Slug: Set all signals that match a regular expression
|
||||
// Slug: Set all signals that match the signal path
|
||||
// Description: Set all signals that match one or more space-separated paths in which `*` can be used as a wildcard
|
||||
|
||||
import { type ActionPlugin, PluginType } from '../../../../engine/types'
|
||||
import { pathMatchesPattern } from '../../../../utils/paths'
|
||||
import { trimDollarSignPrefix } from '../../../../utils/text'
|
||||
|
||||
export const SetAll: ActionPlugin = {
|
||||
type: PluginType.Action,
|
||||
name: 'setAll',
|
||||
fn: ({ signals }, prefix: string, newValue) => {
|
||||
signals.walk((path, signal) => {
|
||||
if (!path.startsWith(prefix)) return
|
||||
signal.value = newValue
|
||||
})
|
||||
fn: ({ signals }, paths: string, newValue) => {
|
||||
let patterns = paths.split(/\s+/).filter((p) => p !== '')
|
||||
patterns = patterns.map((p) => trimDollarSignPrefix(p))
|
||||
|
||||
for (const pattern of patterns) {
|
||||
signals.walk((path, signal) => {
|
||||
if (pathMatchesPattern(path, pattern)) {
|
||||
signal.value = newValue
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,16 +1,25 @@
|
|||
// Authors: Delaney Gillilan
|
||||
// Icon: material-symbols:toggle-off
|
||||
// Slug: Toggle all signals that match a regular expression
|
||||
// Slug: Toggle all signals that match the signal path
|
||||
// Description: Toggle all signals that match one or more space-separated paths in which `*` can be used as a wildcard
|
||||
|
||||
import { type ActionPlugin, PluginType } from '../../../../engine/types'
|
||||
import { pathMatchesPattern } from '../../../../utils/paths'
|
||||
import { trimDollarSignPrefix } from '../../../../utils/text'
|
||||
|
||||
export const ToggleAll: ActionPlugin = {
|
||||
type: PluginType.Action,
|
||||
name: 'toggleAll',
|
||||
fn: ({ signals }, prefix: string) => {
|
||||
signals.walk((path, signal) => {
|
||||
if (!path.startsWith(prefix)) return
|
||||
signal.value = !signal.value
|
||||
})
|
||||
fn: ({ signals }, paths: string) => {
|
||||
let patterns = paths.split(/\s+/).filter((p) => p !== '')
|
||||
patterns = patterns.map((p) => trimDollarSignPrefix(p))
|
||||
|
||||
for (const pattern of patterns) {
|
||||
signals.walk((path, signal) => {
|
||||
if (pathMatchesPattern(path, pattern)) {
|
||||
signal.value = !signal.value
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
export function pathMatchesPattern(path: string, pattern: string) {
|
||||
const regex = new RegExp(
|
||||
`^${pattern.replaceAll('.', '\\.').replaceAll('*', '.*')}$`,
|
||||
)
|
||||
|
||||
return regex.test(path)
|
||||
}
|
|
@ -7,8 +7,8 @@ import "time"
|
|||
const (
|
||||
DatastarKey = "datastar"
|
||||
Version = "1.0.0-beta.10"
|
||||
VersionClientByteSize = 40008
|
||||
VersionClientByteSizeGzip = 14887
|
||||
VersionClientByteSize = 40231
|
||||
VersionClientByteSizeGzip = 14988
|
||||
|
||||
//region Default durations
|
||||
|
||||
|
|
|
@ -55,6 +55,8 @@ func setupTests(ctx context.Context, router chi.Router) (err error) {
|
|||
{ID: "on_signal_change"},
|
||||
{ID: "on_signal_change_path"},
|
||||
{ID: "on_signal_change_path_once"},
|
||||
{ID: "on_signal_change_path_wildcard"},
|
||||
{ID: "persist_signals"},
|
||||
{ID: "plugin_name_prefix"},
|
||||
{ID: "radio_value"},
|
||||
{ID: "ref"},
|
||||
|
@ -62,6 +64,9 @@ func setupTests(ctx context.Context, router chi.Router) (err error) {
|
|||
{ID: "remove_initiating_fragment"},
|
||||
{ID: "select_multiple"},
|
||||
{ID: "select_single"},
|
||||
{ID: "set_all_path"},
|
||||
{ID: "set_all_path_wildcard"},
|
||||
{ID: "set_all_paths"},
|
||||
{ID: "sse_error_event"},
|
||||
{ID: "sse_events"},
|
||||
},
|
||||
|
|
|
@ -5,5 +5,5 @@ import (
|
|||
)
|
||||
|
||||
func TestUnitOnSignalChangePathOnce(t *testing.T) {
|
||||
setupPageTestOnClick(t, "tests/on_signal_change_path_once")
|
||||
setupPageTestOnLoad(t, "tests/on_signal_change_path_once")
|
||||
}
|
||||
|
|
|
@ -5,5 +5,5 @@ import (
|
|||
)
|
||||
|
||||
func TestUnitOnSignalChangePath(t *testing.T) {
|
||||
setupPageTestOnClick(t, "tests/on_signal_change_path")
|
||||
setupPageTestOnLoad(t, "tests/on_signal_change_path")
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package smoketests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUnitOnSignalChangePathWildcard(t *testing.T) {
|
||||
setupPageTestOnLoad(t, "tests/on_signal_change_path_wildcard")
|
||||
}
|
|
@ -5,5 +5,5 @@ import (
|
|||
)
|
||||
|
||||
func TestUnitOnSignalChange(t *testing.T) {
|
||||
setupPageTestOnClick(t, "tests/on_signal_change")
|
||||
setupPageTestOnLoad(t, "tests/on_signal_change")
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package smoketests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/Jeffail/gabs/v2"
|
||||
"github.com/go-rod/rod"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPersistSignals(t *testing.T) {
|
||||
setupPageTest(t, "tests/persist_signals", func(runner runnerFn) {
|
||||
runner("tests/persist_signals", func(t *testing.T, page *rod.Page) {
|
||||
checkLocalStorage := func(path string) string {
|
||||
fromLocalStorage := page.MustEval(`k => localStorage[k]`, "datastar")
|
||||
marshalled := fromLocalStorage.String()
|
||||
c, err := gabs.ParseJSON([]byte(marshalled))
|
||||
assert.NoError(t, err)
|
||||
actual, ok := c.Path(path).Data().(string)
|
||||
assert.True(t, ok)
|
||||
return actual
|
||||
}
|
||||
|
||||
page.MustWaitIdle()
|
||||
assert.Equal(t, "", checkLocalStorage("foo"))
|
||||
assert.Equal(t, "", checkLocalStorage("bar"))
|
||||
assert.Equal(t, "", checkLocalStorage("baz"))
|
||||
page.MustWaitIdle()
|
||||
foo := page.MustElement("#foo")
|
||||
bar := page.MustElement("#bar")
|
||||
foo.MustInput("1")
|
||||
bar.MustInput("1")
|
||||
page.MustWaitIdle()
|
||||
assert.Equal(t, "1", checkLocalStorage("foo"))
|
||||
assert.Equal(t, "1", checkLocalStorage("bar"))
|
||||
assert.Equal(t, "", checkLocalStorage("baz"))
|
||||
})
|
||||
})
|
||||
}
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
func TestExamplePersist(t *testing.T) {
|
||||
setupPageTest(t, "examples/persist", func(runner runnerFn) {
|
||||
t.Skip("skipping test, handled by unit tests")
|
||||
runner("persist", func(t *testing.T, page *rod.Page) {
|
||||
page.MustWaitIdle()
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package smoketests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUnitSetAllPath(t *testing.T) {
|
||||
setupPageTestOnLoad(t, "tests/set_all_path")
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package smoketests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUnitSetAllPathWildcard(t *testing.T) {
|
||||
setupPageTestOnLoad(t, "tests/set_all_path_wildcard")
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package smoketests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUnitSetAllPaths(t *testing.T) {
|
||||
setupPageTestOnLoad(t, "tests/set_all_paths")
|
||||
}
|
|
@ -390,7 +390,7 @@ Now when the `Fetch a question` button is clicked, the server will respond with
|
|||
|
||||
### `data-indicator`
|
||||
|
||||
The [`data-indicator`](/reference/attribute_plugins#data-data-indicator) attribute sets the value of a signal to `true` while the request is in flight, otherwise `false`. We can use this signal to show a loading indicator, which may be desirable for slower responses.
|
||||
The [`data-indicator`](/reference/attribute_plugins#data-indicator) attribute sets the value of a signal to `true` while the request is in flight, otherwise `false`. We can use this signal to show a loading indicator, which may be desirable for slower responses.
|
||||
|
||||
```html
|
||||
<div id="question"></div>
|
||||
|
@ -454,19 +454,19 @@ Actions in Datastar are helper functions that are available in `data-*` attribut
|
|||
|
||||
### `@setAll()`
|
||||
|
||||
The `@setAll()` action sets the values of multiple signals at once. It takes a path prefix that is used to match against signals, and a value to set them to, as arguments.
|
||||
The `@setAll()` action sets the value of all matching signals to the expression provided in the second argument. The first argument can be one or more space-separated paths in which `*` can be used as a wildcard.
|
||||
|
||||
```html
|
||||
<button data-on-click="@setAll('form.', true)"></button>
|
||||
<button data-on-click="@setAll('foo.*', $bar)"></button>
|
||||
```
|
||||
|
||||
This sets the values of all signals namespaced under the `form` signal to `true`, which could be useful for enabling input fields in a form.
|
||||
This sets the values of all signals namespaced under the `foo` signal to the value of `$bar`. This can be useful for checking multiple checkbox fields in a form, for example:
|
||||
|
||||
```html
|
||||
<input type="checkbox" data-bind-checkboxes.checkbox1 /> Checkbox 1
|
||||
<input type="checkbox" data-bind-checkboxes.checkbox2 /> Checkbox 2
|
||||
<input type="checkbox" data-bind-checkboxes.checkbox3 /> Checkbox 3
|
||||
<button data-on-click="@setAll('checkboxes.', true)">Check All</button>
|
||||
<button data-on-click="@setAll('checkboxes.*', true)">Check All</button>
|
||||
```
|
||||
|
||||
<div class="flex flex-col items-start gap-2 p-8 alert">
|
||||
|
@ -488,26 +488,26 @@ This sets the values of all signals namespaced under the `form` signal to `true`
|
|||
<input type="checkbox" data-bind-checkboxes1.checkbox3 class="toggle" />
|
||||
</label>
|
||||
</div>
|
||||
<button data-on-click="@setAll('checkboxes1.', true)" class="mt-4 btn btn-secondary">
|
||||
<button data-on-click="@setAll('checkboxes1.*', true)" class="mt-4 btn btn-secondary">
|
||||
Check All
|
||||
</button>
|
||||
</div>
|
||||
|
||||
### `@toggleAll()`
|
||||
|
||||
The `@toggleAll()` action toggles the values of multiple signals at once. It takes a path prefix that is used to match against signals, as an argument.
|
||||
The `@toggleAll()` action toggles the value of all matching signals. The first argument can be one or more space-separated paths in which `*` can be used as a wildcard.
|
||||
|
||||
```html
|
||||
<button data-on-click="@toggleAll('form.')"></button>
|
||||
<button data-on-click="@toggleAll('foo.*')"></button>
|
||||
```
|
||||
|
||||
This toggles the values of all signals containing `form.` (to either `true` or `false`), which could be useful for toggling input fields in a form.
|
||||
This toggles the values of all signals namespaced under the `foo` signal (to either `true` or `false`). This can be useful for toggling multiple checkbox fields in a form, for example:
|
||||
|
||||
```html
|
||||
<input type="checkbox" data-bind-checkboxes.checkbox1 /> Checkbox 1
|
||||
<input type="checkbox" data-bind-checkboxes.checkbox2 /> Checkbox 2
|
||||
<input type="checkbox" data-bind-checkboxes.checkbox3 /> Checkbox 3
|
||||
<button data-on-click="@toggleAll('checkboxes.')">Toggle All</button>
|
||||
<button data-on-click="@toggleAll('checkboxes.*')">Toggle All</button>
|
||||
```
|
||||
|
||||
<div class="flex flex-col items-start gap-2 p-8 alert">
|
||||
|
@ -529,7 +529,7 @@ This toggles the values of all signals containing `form.` (to either `true` or `
|
|||
<input type="checkbox" data-bind-checkboxes2.checkbox_3 class="toggle" />
|
||||
</label>
|
||||
</div>
|
||||
<button data-on-click="@toggleAll('checkboxes2.')" class="mt-4 btn btn-secondary">
|
||||
<button data-on-click="@toggleAll('checkboxes2.*')" class="mt-4 btn btn-secondary">
|
||||
Toggle All
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -137,22 +137,38 @@ Copies the provided evaluated expression to the clipboard.
|
|||
|
||||
### `@setAll()`
|
||||
|
||||
Arguments: `@setAll(pathPrefix: string, value: any)`
|
||||
Arguments: `@setAll(paths: string, value: any)`
|
||||
|
||||
Sets all the signals that start with the prefix to the expression provided in the second argument. This is useful for setting all the values of a signal namespace at once.
|
||||
Sets the value of all matching signals to the expression provided in the second argument. The first argument can be one or more space-separated signal paths in which `*` can be used as a wildcard.
|
||||
|
||||
```html
|
||||
<div data-on-change="@setAll('foo.', true)"></div>
|
||||
```html
|
||||
<!-- Sets the value of `$foo` to `true` -->
|
||||
<div data-signals-foo="false">
|
||||
<button data-on-click="@setAll('foo', $bar)"></button>
|
||||
</div>
|
||||
|
||||
<!-- Sets the values of `$foo` and `$bar.baz` to `true` -->
|
||||
<div data-signals-foo="false" data-signals-bar.baz="false">
|
||||
<button data-on-click="@setAll('foo bar.*', true)"></button>
|
||||
</div>
|
||||
```
|
||||
|
||||
### `@toggleAll()`
|
||||
|
||||
Arguments: `@toggleAll(pathPrefix: string)`
|
||||
Arguments: `@toggleAll(paths: string)`
|
||||
|
||||
Toggles all the signals that start with the prefix. This is useful for toggling all the values of a signal namespace at once.
|
||||
Toggles the value of all matching signals. The first argument can be one or more space-separated signal paths or namespaced signal paths in which `*` can be used as a wildcard.
|
||||
|
||||
```html
|
||||
<div data-on-click="@toggleAll('foo.')"></div>
|
||||
```html
|
||||
<!-- Toggles the value of `$foo` -->
|
||||
<div data-signals-foo="false">
|
||||
<button data-on-change="@toggleAll('foo')"></button>
|
||||
</div>
|
||||
|
||||
<!-- Toggles the values of `$foo` and `$bar.baz` -->
|
||||
<div data-signals-foo="false" data-signals-bar.baz="false">
|
||||
<button data-on-click="@toggleAll('foo bar.*')"></button>
|
||||
</div>
|
||||
```
|
||||
|
||||
### `@fit()`
|
||||
|
|
|
@ -41,7 +41,7 @@ Datastar provides the following
|
|||
<div>
|
||||
The Datastar <a href="https://marketplace.visualstudio.com/items?itemName=starfederation.datastar-vscode">VSCode
|
||||
extension</a> and <a href="https://plugins.jetbrains.com/plugin/26072-datastar-support">IntelliJ plugin</a>
|
||||
provided autocompletion for all <code>data-*</code> attributes.
|
||||
provide autocompletion for all <code>data-*</code> attributes.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -533,15 +533,16 @@ Modifiers allow you to modify the element intersection behavior and the timing o
|
|||
- `__half` - Triggers when half of the element is visible.
|
||||
- `__full` - Triggers when the full element is visible.
|
||||
- `__debounce` - Debounce the event listener.
|
||||
- `.500ms` - Debounce for 500 milliseconds.
|
||||
- `.1s` - Debounce for 1 second.
|
||||
- `.leading` - Debounce with leading edge.
|
||||
- `.notrail` - Debounce without trailing edge.
|
||||
- `.500ms` - Debounce for 500 milliseconds.
|
||||
- `.1s` - Debounce for 1 second.
|
||||
- `.leading` - Debounce with leading edge.
|
||||
- `.notrail` - Debounce without trailing edge.
|
||||
- `__throttle` - Throttle the event listener.
|
||||
- `.500ms` - Throttle for 500 milliseconds.
|
||||
- `.1s` - Throttle for 1 second.
|
||||
- `.noleading` - Throttle without leading edge.
|
||||
- `.trail` - Throttle with trailing edge.
|
||||
- `.500ms` - Throttle for 500 milliseconds.
|
||||
- `.1s` - Throttle for 1 second.
|
||||
- `.noleading` - Throttle without leading edge.
|
||||
- `.trail` - Throttle with trailing edge.
|
||||
- `__viewtransition` - Wraps the expression in `document.startViewTransition()` when the View Transition API is available.
|
||||
|
||||
```html
|
||||
<div data-on-intersect__once__full="$fullyIntersected = true"></div>
|
||||
|
@ -560,9 +561,10 @@ Runs an expression at a regular interval. The interval duration defaults to 1 se
|
|||
Modifiers allow you to modify the interval duration.
|
||||
|
||||
- `__duration` - Sets the interval duration.
|
||||
- `.500ms` - Interval duration of 500 milliseconds.
|
||||
- `.1s` - Interval duration of 1 second (default).
|
||||
- `.leading` - Execute the first interval immediately.
|
||||
- `.500ms` - Interval duration of 500 milliseconds.
|
||||
- `.1s` - Interval duration of 1 second (default).
|
||||
- `.leading` - Execute the first interval immediately.
|
||||
- `__viewtransition` - Wraps the expression in `document.startViewTransition()` when the View Transition API is available.
|
||||
|
||||
```html
|
||||
<div data-on-interval__duration.500ms="$count++"></div>
|
||||
|
@ -581,8 +583,9 @@ Runs an expression when the element is loaded into the DOM.
|
|||
Modifiers allow you to add a delay to the event listener.
|
||||
|
||||
- `__delay` - Delay the event listener.
|
||||
- `.500ms` - Delay for 500 milliseconds.
|
||||
- `.1s` - Delay for 1 second.
|
||||
- `.500ms` - Delay for 500 milliseconds.
|
||||
- `.1s` - Delay for 1 second.
|
||||
- `__viewtransition` - Wraps the expression in `document.startViewTransition()` when the View Transition API is available.
|
||||
|
||||
```html
|
||||
<div data-on-load__delay.500ms="$count = 1"></div>
|
||||
|
@ -601,15 +604,16 @@ Runs an expression on every [`requestAnimationFrame`](https://developer.mozilla.
|
|||
Modifiers allow you to modify the timing of the event listener.
|
||||
|
||||
- `__debounce` - Debounce the event listener.
|
||||
- `.500ms` - Debounce for 500 milliseconds.
|
||||
- `.1s` - Debounce for 1 second.
|
||||
- `.leading` - Debounce with leading edge.
|
||||
- `.notrail` - Debounce without trailing edge.
|
||||
- `.500ms` - Debounce for 500 milliseconds.
|
||||
- `.1s` - Debounce for 1 second.
|
||||
- `.leading` - Debounce with leading edge.
|
||||
- `.notrail` - Debounce without trailing edge.
|
||||
- `__throttle` - Throttle the event listener.
|
||||
- `.500ms` - Throttle for 500 milliseconds.
|
||||
- `.1s` - Throttle for 1 second.
|
||||
- `.noleading` - Throttle without leading edge.
|
||||
- `.trail` - Throttle with trailing edge.
|
||||
- `.500ms` - Throttle for 500 milliseconds.
|
||||
- `.1s` - Throttle for 1 second.
|
||||
- `.noleading` - Throttle without leading edge.
|
||||
- `.trail` - Throttle with trailing edge.
|
||||
- `__viewtransition` - Wraps the expression in `document.startViewTransition()` when the View Transition API is available.
|
||||
|
||||
```html
|
||||
<div data-on-raf__debounce.10ms="$count++"></div>
|
||||
|
@ -629,20 +633,29 @@ A key can be provided to only trigger the event when a specific signal changes.
|
|||
<div data-on-signal-change-foo="$fooCount++"></div>
|
||||
```
|
||||
|
||||
The signal path can contain `*` as a wildcard.
|
||||
|
||||
```html
|
||||
<div data-signals-foo.bar="1"
|
||||
data-on-signal-change-foo.*="$fooCount++"
|
||||
></div>
|
||||
```
|
||||
|
||||
#### Modifiers
|
||||
|
||||
Modifiers allow you to modify the timing of the event listener.
|
||||
|
||||
- `__debounce` - Debounce the event listener.
|
||||
- `.500ms` - Debounce for 500 milliseconds.
|
||||
- `.1s` - Debounce for 1 second.
|
||||
- `.leading` - Debounce with leading edge.
|
||||
- `.notrail` - Debounce without trailing edge.
|
||||
- `.500ms` - Debounce for 500 milliseconds.
|
||||
- `.1s` - Debounce for 1 second.
|
||||
- `.leading` - Debounce with leading edge.
|
||||
- `.notrail` - Debounce without trailing edge.
|
||||
- `__throttle` - Throttle the event listener.
|
||||
- `.500ms` - Throttle for 500 milliseconds.
|
||||
- `.1s` - Throttle for 1 second.
|
||||
- `.noleading` - Throttle without leading edge.
|
||||
- `.trail` - Throttle with trailing edge.
|
||||
- `.500ms` - Throttle for 500 milliseconds.
|
||||
- `.1s` - Throttle for 1 second.
|
||||
- `.noleading` - Throttle without leading edge.
|
||||
- `.trail` - Throttle with trailing edge.
|
||||
- `__viewtransition` - Wraps the expression in `document.startViewTransition()` when the View Transition API is available.
|
||||
|
||||
```html
|
||||
<div data-on-signal-change__debounce.100ms="$count++"></div>
|
||||
|
|
|
@ -76,9 +76,9 @@ Action plugins are used in Datastar expressions to perform specific actions.
|
|||
|
||||
| Action | Description |
|
||||
|--------|-------------|
|
||||
| [`@setAll()`](/reference/action_plugins#setall) | Sets all signals with a specific prefix to a provided value. |
|
||||
| [`@toggleAll()`](/reference/action_plugins#toggleall) | Toggles all signals that start with a given prefix. |
|
||||
| [`@fit()`](/reference/action_plugins#fit) | Makes a value linearly interpolate from an original range to a new one. |
|
||||
| [`@setAll()`](/reference/action_plugins#setall) | Sets all signal to a provided value. |
|
||||
| [`@toggleAll()`](/reference/action_plugins#toggleall) | Toggles all signal values. |
|
||||
| [`@fit()`](/reference/action_plugins#fit) | Makes a value linearly interpolate. |
|
||||
|
||||
View the [action plugins reference](/reference/action_plugins)
|
||||
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
# On Signal Change
|
||||
|
||||
Tests that a signal change is detected.
|
||||
Tests detecting a signal change.
|
||||
|
||||
<div data-signals="{foo: {bar: 0}, result: 0}" data-on-signal-change="$result = $foo.bar">
|
||||
<button id="clickable" data-on-click="$foo.bar = 1" class="btn">Change</button>
|
||||
<hr />
|
||||
<div data-signals="{foo: {bar: 0}, result: 0}" data-on-signal-change="$result = $foo.bar" data-on-load="$foo.bar = 1">
|
||||
Result:
|
||||
<code id="result" data-text="$result"></code>
|
||||
<hr />
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
# On Signal Change Path
|
||||
|
||||
Tests that a signal change with a path is detected.
|
||||
Tests detecting a signal change with a path.
|
||||
|
||||
<div data-signals="{foo: {bar: 0}, result: 0}" data-on-signal-change-foo="$result = $foo.bar">
|
||||
<button id="clickable" data-on-click="$foo.bar = 1" class="btn">Change</button>
|
||||
<hr />
|
||||
<div data-signals="{foo: 0, result: 0}" data-on-signal-change-foo="$result = $foo" data-on-load="$foo = 1">
|
||||
Result:
|
||||
<code id="result" data-text="$result"></code>
|
||||
<hr />
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
# On Signal Change Path Once
|
||||
|
||||
Tests that a signal change with a path is detected and the expression is called once.
|
||||
Tests detecting a signal change with a path, and that the expression is called once.
|
||||
|
||||
<div data-signals="{foo: {bar: 0}, result: 0}" data-on-signal-change-foo="$result++">
|
||||
<button id="clickable" data-on-click="$foo.bar = 1" class="btn">Change</button>
|
||||
<hr />
|
||||
<div data-signals="{foo: {bar: 0}, result: 0}" data-on-signal-change-foo.bar="$result++" data-on-load="$foo.bar = 1">
|
||||
Result:
|
||||
<code id="result" data-text="$result"></code>
|
||||
<hr />
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
# On Signal Change Path Wildcard
|
||||
|
||||
Tests detecting a signal change with a path using a wildcard.
|
||||
|
||||
<div data-signals="{foo: {bar: 0}, result: 0}" data-on-signal-change-foo.*="$result = $foo.bar" data-on-load="$foo.bar = 1">
|
||||
Result:
|
||||
<code id="result" data-text="$result"></code>
|
||||
<hr />
|
||||
Expected result on click: <code>1</code>
|
||||
</div>
|
|
@ -0,0 +1,8 @@
|
|||
# Persist Signals
|
||||
|
||||
Tests persisting signals.
|
||||
|
||||
<div data-signals="{foo: 0, bar: 0, baz: 0}" data-persist="foo bar" data-on-load="$foo = 1; $bar = 1; $baz = 1">
|
||||
Expected value in local storage (in alphabetical order):
|
||||
<pre><code>datastar: {"bar":1,"foo":1}</code></pre>
|
||||
</div>
|
|
@ -0,0 +1,10 @@
|
|||
# Set All Path
|
||||
|
||||
Tests the set all action on a single path.
|
||||
|
||||
<div data-signals="{foo: false, result: 0}" data-on-load="@setAll('foo', true)">
|
||||
Result:
|
||||
<code id="result" data-text="$result = $foo ? 1 : 0"></code>
|
||||
<hr />
|
||||
Expected result on load: <code>1</code>
|
||||
</div>
|
|
@ -0,0 +1,10 @@
|
|||
# Set All Path Wildcard
|
||||
|
||||
Tests the set all action on a path using a wildcard.
|
||||
|
||||
<div data-signals="{foo: {bar: false}, result: 0}" data-on-load="@setAll('foo.*', true)">
|
||||
Result:
|
||||
<code id="result" data-text="$result = $foo.bar ? 1 : 0"></code>
|
||||
<hr />
|
||||
Expected result on load: <code>1</code>
|
||||
</div>
|
|
@ -0,0 +1,10 @@
|
|||
# Set All Path
|
||||
|
||||
Tests the set all action on multiple paths.
|
||||
|
||||
<div data-signals="{foo: false, bar: false, result: 0}" data-on-load="@setAll('foo bar', true)">
|
||||
Result:
|
||||
<code id="result" data-text="$result = $foo && $bar ? 1 : 0"></code>
|
||||
<hr />
|
||||
Expected result on load: <code>1</code>
|
||||
</div>
|
Loading…
Reference in New Issue