Input Number v1.0
The <e-input-number> component is a component that can be used for .
Usage
An e-input-number has attributes that must be provided,
<e-input-number
id="example id"
value="'1'"
label=""
placeholder=""
/>
Attributes
id | Type: String | required
value | Type: String | Default:''
label | Type: String | Default:''
placeholder | Type: String | Default:''
required | Type: Boolean | Default:false
meta | Type: MetaModel | Default:{ disabled: false, nullable: false }
Examples
Below a few interactive examples of unavailable can be found.
Default
<e-input-number
id="numberInputWithOptions"
:value="'exampleText1'"
/>
Labelled, label='numberInput with Label'
<div class="input-example-field">
<e-input-label
:id="'numberInputWithLabel'"
:value="'numberInput with Label'"
/>
<e-input-number
:id="'numberInputWithLabel'"
:label="'numberInput with Label'"
:value="'1'"
/>
</div>
Source Code
e-input-number.vue
<script setup lang="ts">
import { computed, ref } from 'vue';
import { isNil, clamp } from 'lodash-es';
import { EInput_Number } from 'types/e-input/interfaces/EInput_Number';
export type Props = EInput_Number;
const props = withDefaults(defineProps<Props>(), {
value: '',
label: '',
placeholder: '',
required: false,
meta: () => {
return {
disabled: false,
nullable: false
};
}
});
const emit = defineEmits<{
(e: 'blur', event: FocusEvent): void;
(e: 'keyup.enter', event: KeyboardEvent): void;
(e: 'update:value', value: number): void;
}>();
const input = ref<HTMLInputElement>();
const numberValue = computed(() => {
switch (typeof props.value) {
case 'number':
return props.value;
default:
return Number.parseInt(props.value);
}
});
const isDisabled = computed(() => props.disabled ?? props.meta?.disabled);
const isNullable = computed(() => {
return props.meta?.nullable || false;
});
const hasMinValue = computed(() => !isNil(props.meta.min));
const hasMaxValue = computed(() => !isNil(props.meta.max));
// Ensure acceptable nullish value, fall back to minValue or 0
function confirmNullability(targetValue: number) {
if (Number.isNaN(targetValue)) {
if (!isNullable.value) {
return (props.meta?.min || 0) as number;
} else {
return null;
}
}
return targetValue;
}
// Clamp new value to be within min / max
function clampValue(targetValue: number) {
if (hasMaxValue.value && hasMinValue.value) {
return clamp(targetValue, props.meta.min, props.meta.max);
}
if (hasMaxValue.value) {
return Math.min(targetValue, props.meta.max);
}
if (hasMinValue.value) {
return Math.max(targetValue, props.meta.min);
}
return targetValue;
}
function emitUpdate(event: Event): void {
const target = event.target as HTMLInputElement;
const parsedValue = Number.parseInt(target.value);
let numberValue = confirmNullability(parsedValue);
// Only clamp when there is actual number.
if (numberValue) {
numberValue = clampValue(numberValue);
}
// Update input value, with clamped value
input.value.value = `${numberValue}`;
emit('update:value', numberValue);
}
const timer = ref<NodeJS.Timeout>();
function debounceEmit(event: Event, msDelay: number = 500): void {
clearTimeout(timer.value);
timer.value = setTimeout(() => {
emitUpdate(event);
}, msDelay);
}
</script>
<template>
<input
:id="id"
ref="input"
class="e-input-number"
type="number"
:name="id"
:value="numberValue"
:placeholder="placeholder"
:required="required"
:disabled="isDisabled"
:min="meta.min"
:max="meta.max"
@input="debounceEmit($event, 500)"
@blur="emit('blur', $event)"
@keyup.enter="emit('keyup.enter', $event)"
/>
</template>
<style scoped lang="scss">
.e-input-number {
background-color: var(--e-input-background);
border: none;
border-radius: 15px;
color: var(--e-body-font-color);
font: normal normal normal 16px/20px var(--e-body-font-family);
padding: 15px;
&::placeholder {
color: var(--e-gray-300);
}
&[required] {
+ label::after {
content: '*';
padding-left: 2px;
color: var(--e-required);
font-weight: bold;
}
}
}
</style>