Changing how the the input works. The value

is now binded to the input. Required, min, max
and value are reative to error states.
This commit is contained in:
jqlio18 2022-12-15 12:15:30 -05:00
commit 83030543bf
3 changed files with 41 additions and 38 deletions

View file

@ -33,7 +33,9 @@ Set `required` to `false` to allow for no value.
Set `value` to `null` to denote "no value."
Set `invalid` to `true` to set the input in `invalid` state.
Set `invalid` to `true` to force a `error` state for the input.
The input is reactive to `min`, `max` and `required` attributes.
<FileSource src="/framed/NumberInput/NumberInputEmpty" />

View file

@ -3,14 +3,24 @@
let value = null;
let invalid = false;
let min;
let max;
let required = false;
</script>
<NumberInput required="{false}" bind:value="{value}" invalid="{invalid}" />
<NumberInput
required="{required}"
bind:value="{value}"
max="{max}"
min="{min}"
invalid="{invalid}"
/>
<div style="margin: var(--cds-layout-01) 0">
<Button on:click="{() => (value = null)}">Set to null</Button>
<Button on:click="{() => (value = 0)}">Set to 0</Button>
<Button on:click="{() => (invalid = !invalid)}">Toggle invalid</Button>
<Button on:click="{() => (required = !required)}">Toggle required</Button>
</div>
<p>
@ -21,3 +31,11 @@
<strong>Invalid:</strong>
{invalid}
</p>
<p>
<strong>Required:</strong>
{required}
</p>
<NumberInput required="{false}" bind:value="{max}" label="Max" />
<NumberInput required="{false}" bind:value="{min}" label="Min" />

View file

@ -101,7 +101,7 @@
let error = false;
import { createEventDispatcher, onMount } from "svelte";
import { createEventDispatcher, tick } from "svelte";
import Add from "../icons/Add.svelte";
import Subtract from "../icons/Subtract.svelte";
import WarningFilled from "../icons/WarningFilled.svelte";
@ -121,12 +121,18 @@
} else {
ref.stepDown();
}
value = parse(ref.value);
value = +ref.value;
dispatch("input", value);
dispatch("change", value);
}
async function setErrorState() {
// We need to wait for the values to be synced before checking the validity.
await tick();
error = !ref.checkValidity() || invalid;
}
$: incrementLabel = translateWithId("increment");
$: decrementLabel = translateWithId("decrement");
$: errorId = `error-${id}`;
@ -134,30 +140,7 @@
$$props["aria-label"] ||
"Numeric input field with increment and decrement buttons";
$: if (ref) ref.setCustomValidity(invalid ? invalidText : "");
function parse(raw) {
return raw != "" ? Number(raw) : null;
}
function getValidity() {
return !ref.checkValidity() || invalid;
}
function onInput({ target }) {
error = getValidity();
dispatch("input", parse(target.value));
}
function onChange({ target }) {
error = getValidity();
dispatch("change", parse(target.value));
}
onMount(() => {
error = getValidity();
});
$: value, invalid, required, min, max, setErrorState();
</script>
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
@ -199,31 +182,31 @@
type="number"
pattern="[0-9]*"
aria-describedby="{errorId}"
data-invalid="{invalid || error ? true : undefined}"
aria-invalid="{invalid || error ? true : undefined}"
aria-label="{label ? undefined : ariaLabel}"
data-invalid="{error ? true : undefined}"
aria-invalid="{error ? true : undefined}"
aria-label="{label ? ariaLabel : undefined}"
disabled="{disabled}"
id="{id}"
name="{name}"
max="{max}"
min="{min}"
step="{step}"
value="{value ?? ''}"
bind:value="{value}"
readonly="{readonly}"
required="{required}"
{...$$restProps}
on:change="{onChange}"
on:input="{onInput}"
on:change
on:input
on:keydown
on:keyup
on:focus
on:blur
on:paste
/>
{#if invalid || error}
{#if error}
<WarningFilled class="bx--number__invalid" />
{/if}
{#if !invalid && !error && warn}
{#if !error && warn}
<WarningAltFilled
class="bx--number__invalid bx--number__invalid--warning"
/>
@ -266,7 +249,7 @@
</div>
{/if}
</div>
{#if !invalid && !error && !warn && helperText}
{#if !error && !warn && helperText}
<div
class:bx--form__helper-text="{true}"
class:bx--form__helper-text--disabled="{disabled}"
@ -274,7 +257,7 @@
{helperText}
</div>
{/if}
{#if invalid || error}
{#if error}
<div id="{errorId}" class:bx--form-requirement="{true}">
{invalidText}
</div>