Skip to content

Commit

Permalink
fix(input-number): display value style is broken (#158) (#162)
Browse files Browse the repository at this point in the history
fix #158
  • Loading branch information
kiaking committed Oct 20, 2022
1 parent 48c465d commit 23f3acb
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 73 deletions.
101 changes: 51 additions & 50 deletions lib/components/SInputNumber.vue
Original file line number Diff line number Diff line change
@@ -1,56 +1,35 @@
<template>
<SInputText
class="SInputNumber"
:name="name"
:size="size"
type="number"
:label="label"
:note="note"
:help="help"
:align="align"
:placeholder="placeholder"
:disabled="disabled"
:error-message="errorMessage"
:display-value="displayValue"
:model-value="String(modelValue)"
:validation="validation"
@update:model-value="emitUpdate"
>
<template #before-help>
<p v-if="helpFormat" class="help-text">
{{ valueWithSeparator }}
</p>
</template>
</SInputText>
</template>

<script setup lang="ts">
import { computed, PropType } from 'vue'
import { computed } from 'vue'
import { Validatable } from '../composables/Validation'
import { isNullish } from '../support/Utils'
import SInputText, { Size, Align } from './SInputText.vue'
import SInputText from './SInputText.vue'
const props = defineProps({
size: { type: String as PropType<Size>, default: 'small' },
name: { type: String, default: null },
label: { type: String, default: null },
note: { type: String, default: null },
help: { type: String, default: null },
placeholder: { type: String, default: null },
align: { type: String as PropType<Align>, default: null },
separator: { type: Boolean, default: false },
helpFormat: { type: Boolean, default: false },
disabled: { type: Boolean, default: false },
errorMessage: { type: Boolean, default: true },
modelValue: { type: Number as PropType<number | null>, default: null },
validation: { type: Object as PropType<Validatable>, default: null }
})
export type Size = 'mini' | 'small' | 'medium'
export type Align = 'left' | 'center' | 'right'
const props = defineProps<{
size?: Size
name?: string
label?: string
note?: string
help?: string
placeholder?: string
align?: Align
separator?: boolean
disabled?: boolean
modelValue: number | null
displayValue?: string | null
hideError?: boolean
validation?: Validatable
}>()
const emit = defineEmits(['update:modelValue'])
const emit = defineEmits<{
(e: 'update:modelValue', value: number | null): void
}>()
const valueWithSeparator = computed(() => {
if (isNullish(props.modelValue)) {
return '0'
return null
}
return props.modelValue >= 100000000000000000000
Expand All @@ -59,14 +38,36 @@ const valueWithSeparator = computed(() => {
})
const displayValue = computed(() => {
if (!props.separator || valueWithSeparator.value === '0') {
return null
if (!isNullish(props.displayValue)) {
return props.displayValue
}
return valueWithSeparator.value
return !props.separator || valueWithSeparator.value === null
? null
: valueWithSeparator.value
})
function emitUpdate(value: string | null): void {
emit('update:modelValue', value ? Number(value) : null)
function emitUpdate(value: string | null) {
emit('update:modelValue', isNullish(value) ? null : Number(value))
}
</script>

<template>
<SInputText
class="SInputNumber"
:name="name"
:size="size"
type="number"
:label="label"
:note="note"
:help="help"
:align="align"
:placeholder="placeholder"
:disabled="disabled"
:hide-error="hideError"
:display-value="displayValue"
:model-value="String(modelValue)"
:validation="validation"
@update:model-value="emitUpdate"
/>
</template>
13 changes: 12 additions & 1 deletion lib/components/SInputText.vue
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ function getValue(e: Event | FocusEvent | KeyboardEvent): string | null {
font-size: 14px;
}
.display {
top: 0;
}
.icon {
width: 22px;
height: 30px;
Expand Down Expand Up @@ -172,6 +176,10 @@ function getValue(e: Event | FocusEvent | KeyboardEvent): string | null {
font-size: 16px;
}
.display {
top: 2px;
}
.icon {
width: 26px;
height: 38px;
Expand Down Expand Up @@ -203,6 +211,10 @@ function getValue(e: Event | FocusEvent | KeyboardEvent): string | null {
font-size: 16px;
}
.display {
top: 0;
}
.icon {
width: 28px;
height: 46px;
Expand Down Expand Up @@ -288,7 +300,6 @@ function getValue(e: Event | FocusEvent | KeyboardEvent): string | null {
.display {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
Expand Down
9 changes: 2 additions & 7 deletions stories/components/SInputNumber.story.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,9 @@ const value = ref<number | null>(null)
label="Label"
note="Note text"
help="This is a help text."
placeholder="123456789"
placeholder="123,456,789"
separator
v-model="value"
/>
</Story>
</template>

<docs lang="md">
# SInputNumber


</docs>
48 changes: 33 additions & 15 deletions tests/components/SInputNumber.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { assertEmitted } from 'tests/Utils'

describe('components/SInputNumber', () => {
it('should emit value on input', async () => {
const wrapper = mount(SInputNumber)
const wrapper = mount(SInputNumber, {
props: { modelValue: 1 }
})

await wrapper.find('.SInputNumber .input').setValue('0')
assertEmitted(wrapper, 'update:modelValue', 0, 0)
Expand All @@ -17,7 +19,9 @@ describe('components/SInputNumber', () => {
})

it('should emit null when value is null or empty', async () => {
const wrapper = mount(SInputNumber)
const wrapper = mount(SInputNumber, {
props: { modelValue: 1 }
})

await wrapper.find('.SInputNumber .input').setValue(null)
assertEmitted(wrapper, 'update:modelValue', 0, null)
Expand All @@ -29,20 +33,10 @@ describe('components/SInputNumber', () => {
assertEmitted(wrapper, 'update:modelValue', 2, null)
})

it('should format help text with thousand separator', async () => {
const wrapper = mount(SInputNumber, {
propsData: {
helpFormat: true
}
})

await wrapper.setProps({ modelValue: 1000000000.2222 })
expect((wrapper.vm as any).valueWithSeparator).toBe('1,000,000,000.2222')
})

it('should show the value with thousand separator when the foucs is out', async () => {
const wrapper = mount(SInputNumber, {
propsData: {
props: {
modelValue: null,
separator: true
}
})
Expand All @@ -53,10 +47,34 @@ describe('components/SInputNumber', () => {
})

it('should show the value without thousand separator when separator props is not passed', async () => {
const wrapper = mount(SInputNumber)
const wrapper = mount(SInputNumber, {
props: { modelValue: 1 }
})

await wrapper.setProps({ modelValue: 1000000 })

expect((wrapper.find('.SInputNumber .input').element as any).value).toBe('1000000')
})

it('should not display too large number', async () => {
const wrapper = mount(SInputNumber, {
props: {
separator: true,
modelValue: 100000000000000000000
}
})

expect((wrapper.find('.SInputNumber .display').text())).toBe('The number is too big')
})

it('should display `displayValue` if passed', async () => {
const wrapper = mount(SInputNumber, {
props: {
modelValue: 1,
displayValue: '100'
}
})

expect((wrapper.find('.SInputNumber .display').text())).toBe('100')
})
})

0 comments on commit 23f3acb

Please sign in to comment.