Guide
React, Vue, Svelte and a plain page
React
import { AmountInput } from '@devix-labs/amount-input/react';
<AmountInput
currency="AED"
name="total"
value={total} // a string
onChange={(decimal) => setTotal(decimal)}
/>
value and onChange are decimal strings. There is no number in the API at
all, which is the point — and it is why there is nothing here corresponding to
vue-currency-input #346, "Drop MAX_SAFE_INTEGER limitation".
The widget owns the field's text and React never writes value to the DOM, so a
re-render while someone is typing cannot move the caret.
react-hook-form
<Controller
name="total"
control={control}
render={({ field }) => (
<AmountInput currency="AED" value={field.value} onChange={field.onChange} onBlur={field.onBlur} />
)}
/>
Vue
<script setup>
import { ref } from 'vue';
import { AmountInput } from '@devix-labs/amount-input/vue';
const total = ref('');
</script>
<template>
<AmountInput v-model="total" currency="AED" name="total" />
</template>
Svelte
<script>
import { amountInput } from '@devix-labs/amount-input/svelte';
let total = '';
</script>
<input use:amountInput={{ currency: 'AED', onChange: (v) => (total = v.decimal) }} name="total" />
A web component
<script type="module" src="https://devix.pk/cdn/oss/amount-input@1.0.0/element.js"></script>
<dx-amount-input currency="KWD" name="total" show-currency></dx-amount-input>
Attributes: currency, locale, value, typing, min, max,
show-currency, allow-negative, accounting. It fires change and commit,
and exposes .value, .minor and .instance.
Wrap a field you already have to keep its label, attributes and tab order:
<label for="total">Total</label>
<dx-amount-input currency="AED">
<input id="total" name="total">
</dx-amount-input>
Laravel
The hidden-field behaviour means your controller never knows a widget was
involved — it receives 1234.56, not AED 1,234.56:
<form method="post">
@csrf
<input name="total" id="total" value="{{ old('total', $invoice->total) }}">
</form>
<script type="module">
import { createAmountInput } from '/cdn/oss/amount-input@1.0.0/index.js';
createAmountInput(document.querySelector('#total'), {
currency: @json($invoice->currency),
locale: @json(app()->getLocale()),
});
</script>
$request->validate(['total' => ['required', 'decimal:0,2', 'min:0']]);
Store it in an integer column of minor units, or a decimal(19,4). Not a float,
and not a double — which is the same argument as the rest of this page, one
layer down.
Enhancing fields you already have
document.querySelectorAll('[data-amount]').forEach((field) => {
createAmountInput(field, { currency: field.dataset.amount });
});
<input name="subtotal" data-amount="AED">
<input name="deposit" data-amount="KWD">