FormInput
Text/number/email/password/currency input dengan floating label, char counter, dan validation pipeline bawaan.
Bagian dari: vue-saform · Family: Notch
FormInput menutupi lima mode input sekaligus lewat satu component: text, number, email, password, dan currency — masing-masing map ke native <input type> kecuali currency, yang punya masking thousand/decimal sendiri (locale-aware lewat Intl.NumberFormat) dan hard-reject keystroke non-angka saat diketik, bukan sekadar reformat setelahnya. Password otomatis dapat tombol toggle visibility. prefix/suffix adalah value-transform sungguhan (bukan cuma teks display) yang ikut ter-prepend/append ke value yang di-emit. Floating label, char counter (maxlength), dan validation pipeline (built-in rules + custom validation) sama seperti seluruh Notch family.
Import
import { FormInput } from '@bpmlib/vue-saform';Instalasi: lihat Installation & Setup di halaman utama.
Usage
<script setup lang="ts">
import { ref } from 'vue';
import { FormInput, required, email } from '@bpmlib/vue-saform';
const userEmail = ref('');
const price = ref(0);
</script>
<template>
<FormInput id="email" v-model="userEmail" label="Email" type="email" required :validation="email()" />
<FormInput id="price" v-model="price" label="Harga" type="currency" prefix="Rp" />
</template>API Reference
NOTE
Logic khusus FormInput (currency masking, cursor preservation, prefix/suffix, password toggle) dibangun di atas composable internal useFormInput, tidak diekspos secara publik. Floating label/wrapper state dibangun di atas useFormWrapper, dipakai bersama seluruh Notch family — lihat Core Concepts di halaman utama.
FormInput
Cara Penggunaan:
Root element <div> — child <input> menerima seluruh native attrs yang tidak dideklarasikan sebagai prop lewat attrs fallthrough.
Props
| Name | Type | Default | Description |
|---|---|---|---|
id | string | - | Id input, juga dipakai sebagai name. Wajib. |
label | string | - | Teks floating label |
type | 'text' | 'number' | 'email' | 'password' | 'currency' | 'text' | 'currency' adalah mode custom (masked thousand/decimal formatting sesuai locale), lainnya map langsung ke native <input type> |
placeholder | string | - | |
disabled | boolean | false | |
readonly | boolean | false | Native readonly attribute |
required | boolean | false | Native required attribute + built-in rule required() |
hasError | boolean | false | Paksa visual error state (border merah) terlepas dari internal validation state |
title | string | - | Native title attribute (popup validasi bawaan browser) |
pattern | string | - | Native pattern attribute + built-in rule pattern() |
maxlength | number | string | - | Native maxlength. Saat diset, menampilkan char counter |
minlength | number | string | - | Native minlength + built-in rule minLength() |
maxVal | number | string | - | Native :max + built-in rule max() |
minVal | number | string | - | Native :min + built-in rule min() |
step | number | string | - | Native :step (granularity spinner untuk type="number") |
prefix | string | - | Value-transform, ditampilkan sebagai chip statis dan di-prepend ke value yang di-emit Lihat selengkapnya |
suffix | string | - | Sama seperti prefix, tapi di-append. Hanya diterapkan saat value tidak kosong. Diabaikan saat type="currency" |
locale | string | 'id-ID' | Locale untuk Intl.NumberFormat masking type="currency" |
validation | ValidationInput<unknown> | - | Custom validation rule(s), jalan bersama built-in checks (required/minlength/pattern/email/minVal/maxVal) |
messages | ValidationMessages | - | Override pesan validasi default, di-shallow-merge |
hideValidation | boolean | false | Skip seluruh perhitungan pesan validasi internal |
prefix
Value-transform, bukan sekadar teks display: ditampilkan sebagai chip statis rata-kiri terhadap input (<input> itu sendiri hanya menampilkan/mengedit teks inti yang diketik user), dan di-prepend ke value yang di-emit lewat v-model.
Contoh:
<FormInput id="website" v-model="url" prefix="https://" />
<!-- User ketik "example.com", lihat "example.com", value yang di-emit: "https://example.com" -->Use Case: Menampilkan prefix statis (URL scheme, kode negara, dsb) tanpa user perlu mengetiknya sendiri. Diabaikan saat type="currency" (currency punya display "Rp" kosmetik sendiri yang tidak menyentuh value numerik).
Model
| Name | Type | Default | Description |
|---|---|---|---|
v-model | string | number | '' | Value input. String untuk text/email/password, number untuk currency (nilai numerik mentah, bukan string ter-mask) |
Events
| Name | Payload | Description |
|---|---|---|
change | - | Native change event (fires saat blur setelah value berubah — beda dengan v-model yang update tiap keystroke) |
Slots
| Name | Props | Description |
|---|---|---|
description | - | Baris deskripsi di bawah field |
errors | - | Baris pesan error custom, menggantikan pesan validasi bawaan |
Exposed
| Name | Type | Description |
|---|---|---|
input | Ref<HTMLInputElement | null> | Ref ke elemen <input> native |
triggerFocus() | () => void | Focus input secara programmatic |
validate() | () => Promise<boolean> | Jalankan validasi secara synchronous-feeling, return hasilnya Lihat selengkapnya |
validate()
Method untuk validate input programmatically, misalnya sebelum form submission.
Signature:
validate: () => Promise<boolean>Returns: Promise<boolean> — true jika valid
Contoh:
<script setup lang="ts">
const inputRef = ref();
async function handleSubmit() {
if (await inputRef.value.validate()) {
// submit
}
}
</script>
<template>
<FormInput ref="inputRef" id="name" v-model="name" required />
</template>Contoh:
<FormInput
id="username"
v-model="username"
label="Username"
required
:minlength="4"
:validation="pattern(/^[a-z0-9_]+$/)"
>
<template #description>Huruf kecil, angka, underscore saja.</template>
</FormInput>Examples
1. Password dengan Toggle
Toggle visibility bawaan otomatis muncul saat type="password" — tidak perlu prop tambahan.
<FormInput id="password" v-model="password" type="password" label="Password" required :minlength="8" />2. Currency dengan Prefix
<FormInput id="amount" v-model="amount" type="currency" label="Jumlah" prefix="Rp" locale="id-ID" />3. Custom Error Slot
<FormInput id="code" v-model="code" label="Kode Promo" hide-validation>
<template #errors>
<p v-if="serverError" class="text-red-500 text-sm">{{ serverError }}</p>
</template>
</FormInput>Styling
Styling sepenuhnya self-contained — lihat Import CSS di halaman utama. Component akan tampil fully styled langsung setelah import, tanpa setup tambahan.
CSS Variables
| Variable | Default | Description |
|---|---|---|
--sa-fm-error-list-style | disc | list-style-type untuk error list Lihat selengkapnya |
--sa-fm-error-list-style
Menentukan bullet style pesan error (saat lebih dari satu error muncul sekaligus).
Default: disc
Usage:
:root {
--sa-fm-error-list-style: none;
}Related Components
Bagian dari family Notch:
- FormTextarea — versi
<textarea> - FormSelect — single/multi-select
- FormDatetime — date/time picker