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 `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" /> <FileSource src="/framed/NumberInput/NumberInputEmpty" />

View file

@ -3,14 +3,24 @@
let value = null; let value = null;
let invalid = false; let invalid = false;
let min;
let max;
let required = false;
</script> </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"> <div style="margin: var(--cds-layout-01) 0">
<Button on:click="{() => (value = null)}">Set to null</Button> <Button on:click="{() => (value = null)}">Set to null</Button>
<Button on:click="{() => (value = 0)}">Set to 0</Button> <Button on:click="{() => (value = 0)}">Set to 0</Button>
<Button on:click="{() => (invalid = !invalid)}">Toggle invalid</Button> <Button on:click="{() => (invalid = !invalid)}">Toggle invalid</Button>
<Button on:click="{() => (required = !required)}">Toggle required</Button>
</div> </div>
<p> <p>
@ -21,3 +31,11 @@
<strong>Invalid:</strong> <strong>Invalid:</strong>
{invalid} {invalid}
</p> </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; let error = false;
import { createEventDispatcher, onMount } from "svelte"; import { createEventDispatcher, tick } from "svelte";
import Add from "../icons/Add.svelte"; import Add from "../icons/Add.svelte";
import Subtract from "../icons/Subtract.svelte"; import Subtract from "../icons/Subtract.svelte";
import WarningFilled from "../icons/WarningFilled.svelte"; import WarningFilled from "../icons/WarningFilled.svelte";
@ -121,12 +121,18 @@
} else { } else {
ref.stepDown(); ref.stepDown();
} }
value = parse(ref.value); value = +ref.value;
dispatch("input", value); dispatch("input", value);
dispatch("change", 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"); $: incrementLabel = translateWithId("increment");
$: decrementLabel = translateWithId("decrement"); $: decrementLabel = translateWithId("decrement");
$: errorId = `error-${id}`; $: errorId = `error-${id}`;
@ -134,30 +140,7 @@
$$props["aria-label"] || $$props["aria-label"] ||
"Numeric input field with increment and decrement buttons"; "Numeric input field with increment and decrement buttons";
$: if (ref) ref.setCustomValidity(invalid ? invalidText : ""); $: if (ref) ref.setCustomValidity(invalid ? invalidText : "");
$: value, invalid, required, min, max, setErrorState();
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();
});
</script> </script>
<!-- svelte-ignore a11y-mouse-events-have-key-events --> <!-- svelte-ignore a11y-mouse-events-have-key-events -->
@ -199,31 +182,31 @@
type="number" type="number"
pattern="[0-9]*" pattern="[0-9]*"
aria-describedby="{errorId}" aria-describedby="{errorId}"
data-invalid="{invalid || error ? true : undefined}" data-invalid="{error ? true : undefined}"
aria-invalid="{invalid || error ? true : undefined}" aria-invalid="{error ? true : undefined}"
aria-label="{label ? undefined : ariaLabel}" aria-label="{label ? ariaLabel : undefined}"
disabled="{disabled}" disabled="{disabled}"
id="{id}" id="{id}"
name="{name}" name="{name}"
max="{max}" max="{max}"
min="{min}" min="{min}"
step="{step}" step="{step}"
value="{value ?? ''}" bind:value="{value}"
readonly="{readonly}" readonly="{readonly}"
required="{required}" required="{required}"
{...$$restProps} {...$$restProps}
on:change="{onChange}" on:change
on:input="{onInput}" on:input
on:keydown on:keydown
on:keyup on:keyup
on:focus on:focus
on:blur on:blur
on:paste on:paste
/> />
{#if invalid || error} {#if error}
<WarningFilled class="bx--number__invalid" /> <WarningFilled class="bx--number__invalid" />
{/if} {/if}
{#if !invalid && !error && warn} {#if !error && warn}
<WarningAltFilled <WarningAltFilled
class="bx--number__invalid bx--number__invalid--warning" class="bx--number__invalid bx--number__invalid--warning"
/> />
@ -266,7 +249,7 @@
</div> </div>
{/if} {/if}
</div> </div>
{#if !invalid && !error && !warn && helperText} {#if !error && !warn && helperText}
<div <div
class:bx--form__helper-text="{true}" class:bx--form__helper-text="{true}"
class:bx--form__helper-text--disabled="{disabled}" class:bx--form__helper-text--disabled="{disabled}"
@ -274,7 +257,7 @@
{helperText} {helperText}
</div> </div>
{/if} {/if}
{#if invalid || error} {#if error}
<div id="{errorId}" class:bx--form-requirement="{true}"> <div id="{errorId}" class:bx--form-requirement="{true}">
{invalidText} {invalidText}
</div> </div>