mirror of
https://github.com/element-plus/element-plus.git
synced 2025-01-12 10:45:10 +08:00
fix: date picker support value-format (#2120)
Co-authored-by: yangyu8 <yangyu8@kingsoft.com>
This commit is contained in:
parent
77631999d1
commit
da622e10d1
@ -4,6 +4,7 @@ import dayjs from 'dayjs'
|
||||
import 'dayjs/locale/zh-cn'
|
||||
import { nextTick } from 'vue'
|
||||
import DatePicker from '../src/date-picker'
|
||||
import Input from '@element-plus/input'
|
||||
|
||||
const _mount = (template: string, data = () => ({}), otherObj?) => mount({
|
||||
components: {
|
||||
@ -192,6 +193,48 @@ describe('DatePicker', () => {
|
||||
const attr = popperEl.getAttribute('aria-hidden')
|
||||
expect(attr).toEqual('false')
|
||||
})
|
||||
|
||||
describe('value-format', () => {
|
||||
it('with literal string', async () => {
|
||||
const day = dayjs()
|
||||
const format = 'YYYY-MM-DD'
|
||||
const valueFormat = '[Element-Plus] DD/MM YYYY'
|
||||
const value = day.format(valueFormat)
|
||||
const wrapper = _mount(`
|
||||
<el-date-picker
|
||||
ref="compo"
|
||||
v-model="value"
|
||||
type="date"
|
||||
format="${format}"
|
||||
value-format="${valueFormat}" />
|
||||
<button @click="changeValue">click</button>
|
||||
`, () => {
|
||||
return {
|
||||
value,
|
||||
}
|
||||
}, {
|
||||
methods: {
|
||||
changeValue () {
|
||||
this.value = '[Element-Plus] 31/05 2021'
|
||||
},
|
||||
},
|
||||
})
|
||||
const vm = wrapper.vm as any
|
||||
const input = wrapper.find('input')
|
||||
input.trigger('blur')
|
||||
input.trigger('focus')
|
||||
await nextTick()
|
||||
{
|
||||
(document.querySelector('td.available') as HTMLElement).click()
|
||||
}
|
||||
await nextTick()
|
||||
expect(vm.value).toBe(dayjs(`[Element-Plus] 01/${('0' + (day.month() + 1)).slice(-2)} ${day.year()}`, valueFormat).format(valueFormat))
|
||||
wrapper.find('button').trigger('click')
|
||||
await nextTick()
|
||||
expect(wrapper.findComponent(Input).vm.modelValue).toBe('2021-05-31')
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
describe('DatePicker Navigation', () => {
|
||||
@ -299,6 +342,29 @@ describe('MonthPicker', () => {
|
||||
const vm = wrapper.vm as any
|
||||
expect(vm.value.getMonth()).toBe(0)
|
||||
})
|
||||
|
||||
it('value-format', async () => {
|
||||
const valueFormat = '[Element-Plus] YYYY.MM'
|
||||
const wrapper = _mount(`
|
||||
<el-date-picker
|
||||
type="month"
|
||||
v-model="value"
|
||||
value-format="${valueFormat}"
|
||||
></el-date-picker>
|
||||
`, () => ({ value: dayjs(new Date(2020, 7, 1)).format(valueFormat) }))
|
||||
await nextTick()
|
||||
expect(wrapper.findComponent(Input).vm.modelValue).toBe('2020-08')
|
||||
const input = wrapper.find('input')
|
||||
input.trigger('blur')
|
||||
input.trigger('focus')
|
||||
await nextTick()
|
||||
{
|
||||
(document.querySelector('.el-month-table a.cell') as HTMLElement).click()
|
||||
}
|
||||
await nextTick()
|
||||
expect(wrapper.findComponent(Input).vm.modelValue).toBe('2020-01')
|
||||
expect((wrapper.vm as any).value).toBe(dayjs(new Date(2020, 0, 1)).format(valueFormat))
|
||||
})
|
||||
})
|
||||
|
||||
describe('YearPicker', () => {
|
||||
@ -333,6 +399,27 @@ describe('YearPicker', () => {
|
||||
const vm = wrapper.vm as any
|
||||
expect(vm.value.getFullYear()).toBe(2030)
|
||||
})
|
||||
|
||||
it('value-format', async () => {
|
||||
const valueFormat = '[Element-Plus] YYYY'
|
||||
const wrapper = _mount(`
|
||||
<el-date-picker
|
||||
type="year"
|
||||
v-model="value"
|
||||
value-format="${valueFormat}"
|
||||
></el-date-picker>
|
||||
`, () => ({ value: dayjs(new Date(2005, 7, 1)).format(valueFormat) }))
|
||||
await nextTick()
|
||||
expect(wrapper.findComponent(Input).vm.modelValue).toBe('2005')
|
||||
const input = wrapper.find('input')
|
||||
input.trigger('blur')
|
||||
input.trigger('focus')
|
||||
await nextTick()
|
||||
const cell = (document.querySelector('.el-year-table a.cell') as HTMLElement)
|
||||
cell.click()
|
||||
await nextTick()
|
||||
expect((wrapper.vm as any).value).toBe(dayjs(new Date(Number.parseInt(cell.innerHTML.trim()), 0, 1)).format(valueFormat))
|
||||
})
|
||||
})
|
||||
|
||||
describe('WeekPicker', () => {
|
||||
@ -595,6 +682,34 @@ describe('DateRangePicker', () => {
|
||||
expect(startDate.length).toBe(1)
|
||||
expect(endDate.length).toBe(1)
|
||||
})
|
||||
|
||||
it('value-format', async () => {
|
||||
const valueFormat = 'DD/MM YYYY'
|
||||
const wrapper = _mount( `
|
||||
<el-date-picker
|
||||
v-model="value"
|
||||
type="daterange"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="${valueFormat}"
|
||||
/>`, () => ({ value: [
|
||||
dayjs(new Date(2021, 4, 2)).format(valueFormat),
|
||||
dayjs(new Date(2021, 4, 12)).format(valueFormat),
|
||||
] }))
|
||||
await nextTick()
|
||||
const [startInput, endInput] = wrapper.findAll('input')
|
||||
expect(startInput.element.value).toBe('2021-05-02')
|
||||
expect(endInput.element.value).toBe('2021-05-12')
|
||||
startInput.trigger('blur')
|
||||
startInput.trigger('focus')
|
||||
await nextTick()
|
||||
const panels = document.querySelectorAll('.el-date-range-picker__content')
|
||||
expect(panels.length).toBe(2);
|
||||
(panels[0].querySelector('td.available') as HTMLElement).click()
|
||||
await nextTick();
|
||||
(panels[1].querySelector('td.available') as HTMLElement).click()
|
||||
await nextTick()
|
||||
expect((wrapper.vm as any).value.toString()).toBe([ '01/05 2021', '01/06 2021' ].toString())
|
||||
})
|
||||
})
|
||||
|
||||
describe('MonthRange', () => {
|
||||
|
@ -130,12 +130,12 @@ import {
|
||||
watch,
|
||||
provide,
|
||||
} from 'vue'
|
||||
import dayjs from 'dayjs'
|
||||
import dayjs, { Dayjs } from 'dayjs'
|
||||
import { ClickOutside } from '@element-plus/directives'
|
||||
import ElInput from '@element-plus/input'
|
||||
import ElPopper from '@element-plus/popper'
|
||||
import { EVENT_CODE } from '@element-plus/utils/aria'
|
||||
import { useGlobalConfig } from '@element-plus/utils/util'
|
||||
import { useGlobalConfig, isEmpty } from '@element-plus/utils/util'
|
||||
import { elFormKey, elFormItemKey } from '@element-plus/form'
|
||||
import { defaultProps } from './props'
|
||||
import type { ElFormContext, ElFormItemContext } from '@element-plus/form'
|
||||
@ -180,6 +180,15 @@ const valueEquals = function(a, b) {
|
||||
return false
|
||||
}
|
||||
|
||||
const parser = function(date: Date | string, format: string): Dayjs {
|
||||
const day = isEmpty(format) ? dayjs(date) : dayjs(date, format)
|
||||
return day.isValid() ? day : undefined
|
||||
}
|
||||
|
||||
const formatter = function(date: Date, format: string) {
|
||||
return isEmpty(format) ? date : dayjs(date).format(format)
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Picker',
|
||||
components: {
|
||||
@ -223,7 +232,13 @@ export default defineComponent({
|
||||
}
|
||||
const emitInput = val => {
|
||||
if (!valueEquals(props.modelValue, val)) {
|
||||
ctx.emit('update:modelValue', val)
|
||||
let formatValue
|
||||
if (Array.isArray(val)) {
|
||||
formatValue = val.map(_ => formatter(_, props.valueFormat))
|
||||
} else if(val) {
|
||||
formatValue = formatter(val, props.valueFormat)
|
||||
}
|
||||
ctx.emit('update:modelValue', val ? formatValue : val)
|
||||
}
|
||||
}
|
||||
const refInput = computed(() => {
|
||||
@ -274,15 +289,18 @@ export default defineComponent({
|
||||
}
|
||||
} else {
|
||||
if (Array.isArray(props.modelValue)) {
|
||||
result = props.modelValue.map(_=>dayjs(_))
|
||||
result = props.modelValue.map(_=> parser(_, props.valueFormat))
|
||||
} else {
|
||||
result = dayjs(props.modelValue as Date)
|
||||
result = parser(props.modelValue as Date, props.valueFormat)
|
||||
}
|
||||
}
|
||||
|
||||
if (pickerOptions.value.getRangeAvaliableTime) {
|
||||
result = pickerOptions.value.getRangeAvaliableTime(result)
|
||||
}
|
||||
if (Array.isArray(result) && result.some(_ => !_)) {
|
||||
result = []
|
||||
}
|
||||
return result
|
||||
})
|
||||
|
||||
|
@ -13,6 +13,9 @@ export const defaultProps = {
|
||||
format: {
|
||||
type: String,
|
||||
},
|
||||
valueFormat: {
|
||||
type: String as PropType<string>,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: '',
|
||||
|
@ -333,6 +333,17 @@ Pay attention to capitalization
|
||||
format="YYYY/MM/DD">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
<div class="block">
|
||||
<span class="demonstration">Use value-format</span>
|
||||
<div class="demonstration">Value:{{ value2 }}</div>
|
||||
<el-date-picker
|
||||
v-model="value2"
|
||||
type="date"
|
||||
placeholder="Pick a Date"
|
||||
format="YYYY/MM/DD"
|
||||
value-format="YYYY-MM-DD">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -340,6 +351,7 @@ Pay attention to capitalization
|
||||
data() {
|
||||
return {
|
||||
value1: '',
|
||||
value2: ''
|
||||
};
|
||||
}
|
||||
};
|
||||
@ -407,6 +419,7 @@ Note, date time locale (month name, first day of the week ...) are also configed
|
||||
| range-separator | range separator | string | — | '-' |
|
||||
| default-value | optional, default date of the calendar | Date | anything accepted by `new Date()` | — |
|
||||
| default-time | optional, the time value to use when selecting date range | Date[] | Array with length 2, each item is a Date. The first item for the start date and then second item for the end date | — |
|
||||
| value-format | optional, format of binding value. If not specified, the binding value will be a Date object | string | see [date formats](#/en-US/component/date-picker#date-formats) | — |
|
||||
| name | same as `name` in native input | string | — | — |
|
||||
| unlink-panels | unlink two date-panels in range-picker | boolean | — | false |
|
||||
| prefix-icon | Custom prefix icon class | string | — | el-icon-date |
|
||||
|
@ -335,6 +335,17 @@ Preste atención a la capitalización
|
||||
format="YYYY/MM/DD">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
<div class="block">
|
||||
<span class="demonstration">Use value-format</span>
|
||||
<div class="demonstration">Value:{{ value2 }}</div>
|
||||
<el-date-picker
|
||||
v-model="value2"
|
||||
type="date"
|
||||
placeholder="Pick a Date"
|
||||
format="YYYY/MM/DD"
|
||||
value-format="YYYY-MM-DD">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -412,6 +423,7 @@ Note, date time locale (month name, first day of the week ...) are also configed
|
||||
| range-separator | separador de rangos | string | — | '-' |
|
||||
| default-value | opcional, valor por defecto para el calendario | Date | cualquiera aceptado por `new Date()` | — |
|
||||
| default-time | optional, the time value to use when selecting date range | Date[] | Array with length 2, each item is a Date. The first item for the start date and then second item for the end date | — |
|
||||
| value-format | opcional, formato del valor enlazado. Si no esta especificado, el valor enlazado será un objeto Date. | string | ver [date formats](#/es/component/date-picker#date-formats) | — |
|
||||
| name | igual que `name` en el input nativo | string | — | — |
|
||||
| unlink-panels | desvincular los dos paneles de fecha en el range-picker | boolean | — | false |
|
||||
| prefix-icon | Clase personalizada para el icono prefijado | string | — | el-icon-date |
|
||||
|
@ -333,6 +333,17 @@ Attention à la capitalisation !
|
||||
format="YYYY/MM/DD">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
<div class="block">
|
||||
<span class="demonstration">Utilise value-format</span>
|
||||
<div class="demonstration">Value:{{ value2 }}</div>
|
||||
<el-date-picker
|
||||
v-model="value2"
|
||||
type="date"
|
||||
placeholder="Sélectionnez une date"
|
||||
format="YYYY/MM/DD"
|
||||
value-format="YYYY-MM-DD">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -409,6 +420,7 @@ Note, date time locale (month name, first day of the week ...) are also configed
|
||||
| range-separator | Séparateur de plage de dates. | string | — | '-' |
|
||||
| default-value | Date par défaut du calendrier, optionnelle. | Date | Tout ce qui est accepté par `new Date()` | — |
|
||||
| default-time | optional, the time value to use when selecting date range | Date[] | Array with length 2, each item is a Date. The first item for the start date and then second item for the end date | — |
|
||||
| value-format | Format de la variable stockée, optionnel. Si non spécifié, la valeur sera un objet Date. | string | Voir [formats de date](#/fr-FR/component/date-picker#formats-de-date). | — |
|
||||
| name | Identique au `name` de l'input natif | string | — | — |
|
||||
| unlink-panels | Rend indépendants les deux panneaux de plage de dates. | boolean | — | false |
|
||||
| prefix-icon | Icône de préfixe. | string | — | el-icon-date |
|
||||
|
@ -329,6 +329,17 @@ Check the list [here](https://day.js.org/docs/en/display/format#list-of-all-avai
|
||||
format="yyyy/MM/dd">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
<div class="block">
|
||||
<span class="demonstration">Use value-format</span>
|
||||
<div class="demonstration">Value:{{ value2 }}</div>
|
||||
<el-date-picker
|
||||
v-model="value2"
|
||||
type="date"
|
||||
placeholder="Pick a Date"
|
||||
format="YYYY/MM/DD"
|
||||
value-format="YYYY-MM-DD">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -405,6 +416,7 @@ Note, date time locale (month name, first day of the week ...) are also configed
|
||||
| range-separator | 範囲セパレータ | string | — | '-' |
|
||||
| default-value | オプション、カレンダーのデフォルトの日付 | Date | anything accepted by `new Date()` | — |
|
||||
| default-time | optional, the time value to use when selecting date range | Date[] | Array with length 2, each item is a Date. The first item for the start date and then second item for the end date | — |
|
||||
| value-format | optional, format of binding value. If not specified, the binding value will be a Date object | string | see [date formats](#/en-US/component/date-picker#date-formats) | — |
|
||||
| name | ネイティブ入力の `name` と同じ | string | — | — |
|
||||
| unlink-panels | 範囲ピッカーで2つのデータパネルのリンクを解除する | boolean | — | false |
|
||||
| prefix-icon | カスタムプレフィックスアイコン | string | — | el-icon-date |
|
||||
|
@ -331,6 +331,17 @@
|
||||
format="YYYY 年 MM 月 DD 日">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
<div class="block">
|
||||
<span class="demonstration">使用value-format</span>
|
||||
<div class="demonstration">值:{{ value2 }}</div>
|
||||
<el-date-picker
|
||||
v-model="value2"
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
format="YYYY 年 MM 月 DD 日"
|
||||
value-format="YYYY/MM/DD">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -407,6 +418,7 @@
|
||||
| range-separator | 选择范围时的分隔符 | string | — | '-' |
|
||||
| default-value | 可选,选择器打开时默认显示的时间 | Date | 可被`new Date()`解析 | — |
|
||||
| default-time | 范围选择时选中日期所使用的当日内具体时刻 | Date[] | 数组,长度为 2,第一项指定开始日期的时刻,第二项指定结束日期的时刻,不指定会使用时刻 `00:00:00` | — |
|
||||
| value-format | 可选,绑定值的格式。不指定则绑定值为 Date 对象 | string | 见[日期格式](#/zh-CN/component/date-picker#ri-qi-ge-shi) | — |
|
||||
| name | 原生属性 | string | — | — |
|
||||
| unlink-panels | 在范围选择器里取消两个日期面板之间的联动 | boolean | — | false |
|
||||
| prefix-icon | 自定义头部图标的类名 | string | — | el-icon-date |
|
||||
|
Loading…
Reference in New Issue
Block a user