Helpers
Auto-imported utility classes. Type in the inputs: the tables call the real functions.
Source in the kit: utils/ · composables/useWatch.ts
NumberHelper
examples/helpers/Number.vue| NumberHelper.withComma(value) | 1,234,567.891 |
| NumberHelper.withFixed(value) | 1,234,567.89 |
| NumberHelper.toCurrency(value) | 1,234,567.89 |
| NumberHelper.toCurrency(value, 'THB') | THB 1,234,567.89 |
| NumberHelper.toNumber(value) | 1234567.891 |
<template>
<div class="space-y-3">
<Input
v-model="input"
class="w-56"
/>
<table class="w-full text-sm">
<tbody class="divide-y divide-gray-100">
<tr
v-for="row in rows"
:key="row.call"
>
<td class="py-1.5 pr-4 font-mono text-xs text-gray-500">
{{ row.call }}
</td>
<td class="py-1.5 font-medium">
{{ row.result }}
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script lang="ts" setup>
const input = ref('1234567.891')
// All of them accept a number or a numeric string, and treat empty input as 0
const rows = computed(() => [
{
call: 'NumberHelper.withComma(value)',
result: NumberHelper.withComma(input.value),
},
{
call: 'NumberHelper.withFixed(value)',
result: NumberHelper.withFixed(input.value),
},
{
call: 'NumberHelper.toCurrency(value)',
result: NumberHelper.toCurrency(input.value),
},
{
call: "NumberHelper.toCurrency(value, 'THB')",
result: NumberHelper.toCurrency(input.value, 'THB'),
},
{
call: 'NumberHelper.toNumber(value)',
result: NumberHelper.toNumber(input.value),
},
])
</script>TimeHelper
examples/helpers/Time.vue Formats, time zone and Thai year come from app.config.ts . This playground sets is_thai_year: true .
| TimeHelper.displayDate(value) | 21 ก.พ. 2567 |
| TimeHelper.displayDateTime(value) | 21 ก.พ. 2567 01:30 |
| TimeHelper.displayDateThai(value) | 21 ก.พ. 2567 |
| TimeHelper.displayDateRange(value, value).startDate | 21 ก.พ. 2567 |
| TimeHelper.getDateFormTime(value) | 2024-02-20 |
| TimeHelper.getDateTimeFormTime(value) | 2024-02-20 18:30:00 |
| TimeHelper.getTimeFormTime(value) | 18:30 |
| TimeHelper.getISODateTimeFormTime(value) | 2024-02-20T18:30:00Z |
| TimeHelper.toUTC(value) | 2024-02-20 18:30:00 |
| TimeHelper.getCurrentDate() | 2026-11-06 |
<template>
<div class="space-y-3">
<Input
v-model="input"
class="w-72"
/>
<table class="w-full text-sm">
<tbody class="divide-y divide-gray-100">
<tr
v-for="row in rows"
:key="row.call"
>
<td class="py-1.5 pr-4 font-mono text-xs text-gray-500">
{{ row.call }}
</td>
<td class="py-1.5 font-medium">
{{ row.result ?? 'null' }}
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script lang="ts" setup>
// Any ISO string or Date. Try an empty value: every function answers null instead of "Invalid Date".
const input = ref('2024-02-20T18:30:00Z')
// display* are for people: core.date_format / date_time_format, core.time_zone, Thai year and month if enabled.
// get* are for the API: core.date_format_system / date_time_format_system.
const rows = computed(() => [
{
call: 'TimeHelper.displayDate(value)',
result: TimeHelper.displayDate(input.value),
},
{
call: 'TimeHelper.displayDateTime(value)',
result: TimeHelper.displayDateTime(input.value),
},
{
call: 'TimeHelper.displayDateThai(value)',
result: TimeHelper.displayDateThai(input.value),
},
{
call: 'TimeHelper.displayDateRange(value, value).startDate',
result: TimeHelper.displayDateRange(input.value, input.value).startDate,
},
{
call: 'TimeHelper.getDateFormTime(value)',
result: TimeHelper.getDateFormTime(input.value),
},
{
call: 'TimeHelper.getDateTimeFormTime(value)',
result: TimeHelper.getDateTimeFormTime(input.value),
},
{
call: 'TimeHelper.getTimeFormTime(value)',
result: TimeHelper.getTimeFormTime(input.value),
},
{
call: 'TimeHelper.getISODateTimeFormTime(value)',
result: TimeHelper.getISODateTimeFormTime(input.value),
},
{
call: 'TimeHelper.toUTC(value)',
result: TimeHelper.toUTC(input.value),
},
{
call: 'TimeHelper.getCurrentDate()',
result: TimeHelper.getCurrentDate(),
},
])
</script>ArrayHelper, ObjectHelper, StringHelper, ParamHelper
examples/helpers/Data.vue| ArrayHelper.toOptions(provinces) | [{"value":10,"label":"Bangkok"},{"value":50,"label":"Chiang Mai"}] |
| ArrayHelper.toOptions(provinces, 'meta.code', 'name') | [{"value":"BKK","label":"Bangkok"},{"value":"CNX","label":"Chiang Mai"}] |
| ArrayHelper.toArray(null) | [] |
| ArrayHelper.isEmpty([]) | true |
| ObjectHelper.toOption(provinces[0]) | {"value":10,"label":"Bangkok"} |
| ObjectHelper.isEmpty({}) | true |
| StringHelper.getError(apiError) | "Email is already taken" |
| StringHelper.getError(null, 'Try again later') | "Try again later" |
| ObjectHelper.isInvalidParams(apiError) | true |
| ParamHelper.isNotFoundError({ code: 'NOT_FOUND' }) | true |
| StringHelper.truncate('A very long sentence', 10) | "A very lon..." |
| StringHelper.joinURL('https://api.test/', '/users', '1') | "https://api.test/users/1" |
<template>
<table class="w-full text-sm">
<tbody class="divide-y divide-gray-100">
<tr
v-for="row in rows"
:key="row.call"
>
<td class="py-1.5 pr-4 align-top font-mono text-xs text-gray-500">
{{ row.call }}
</td>
<td class="py-1.5 font-mono text-xs">
{{ JSON.stringify(row.result) }}
</td>
</tr>
</tbody>
</table>
</template>
<script lang="ts" setup>
const provinces = [
{
id: 10,
name: 'Bangkok',
meta: {
code: 'BKK',
},
},
{
id: 50,
name: 'Chiang Mai',
meta: {
code: 'CNX',
},
},
]
const apiError = {
code: 'INVALID_PARAMS',
message: 'Invalid parameters',
fields: {
email: {
message: 'Email is already taken',
},
},
}
const rows = [
{
// API list -> select options. Attribute names can be paths.
call: 'ArrayHelper.toOptions(provinces)',
result: ArrayHelper.toOptions(provinces),
},
{
call: "ArrayHelper.toOptions(provinces, 'meta.code', 'name')",
result: ArrayHelper.toOptions(provinces, 'meta.code', 'name'),
},
{
call: 'ArrayHelper.toArray(null)',
result: ArrayHelper.toArray(null),
},
{
call: 'ArrayHelper.isEmpty([])',
result: ArrayHelper.isEmpty([]),
},
{
call: 'ObjectHelper.toOption(provinces[0])',
result: ObjectHelper.toOption(provinces[0]),
},
{
call: 'ObjectHelper.isEmpty({})',
result: ObjectHelper.isEmpty({}),
},
{
// The one to remember: turns any API error into a sentence for the user
call: 'StringHelper.getError(apiError)',
result: StringHelper.getError(apiError),
},
{
call: "StringHelper.getError(null, 'Try again later')",
result: StringHelper.getError(null, 'Try again later'),
},
{
call: 'ObjectHelper.isInvalidParams(apiError)',
result: ObjectHelper.isInvalidParams(apiError),
},
{
call: "ParamHelper.isNotFoundError({ code: 'NOT_FOUND' })",
result: ParamHelper.isNotFoundError({
code: 'NOT_FOUND',
}),
},
{
call: "StringHelper.truncate('A very long sentence', 10)",
result: StringHelper.truncate('A very long sentence', 10),
},
{
call: "StringHelper.joinURL('https://api.test/', '/users', '1')",
result: StringHelper.joinURL('https://api.test/', '/users', '1'),
},
]
</script>useWatchTrue, useWatchFalse, useWatchChange
examples/helpers/Watch.vueisOpen = false
<template>
<div class="space-y-3">
<div class="flex items-center gap-3">
<Switch v-model="isOpen" />
<span class="text-sm">isOpen = {{ isOpen }}</span>
</div>
<ul class="text-sm text-gray-600">
<li
v-for="(entry, index) in log"
:key="index"
>
{{ entry }}
</li>
</ul>
</div>
</template>
<script lang="ts" setup>
const isOpen = ref(false)
const log = ref<string[]>([])
// A plain watch fires on every change, so callbacks start with `if (value)`.
// These fire only on the transition you care about, which is how pages react to loader status.
useWatchTrue(
() => isOpen.value,
() => log.value.push('useWatchTrue: became true')
)
useWatchFalse(
() => isOpen.value,
() => log.value.push('useWatchFalse: became false')
)
useWatchChange(
() => isOpen.value,
(value, oldValue) => log.value.push(`useWatchChange: ${oldValue} -> ${value}`)
)
</script>