mirror of
https://github.com/tenrok/vue2-datepicker.git
synced 2026-06-21 11:50:36 +03:00
feat: support custom format function
This commit is contained in:
@@ -85,7 +85,7 @@ export default {
|
|||||||
|------|--------------|-------|---------|
|
|------|--------------|-------|---------|
|
||||||
| type | select date type | 'date' \| 'datetime' \| 'year' \| 'month' \| 'time' | 'date' |
|
| type | select date type | 'date' \| 'datetime' \| 'year' \| 'month' \| 'time' | 'date' |
|
||||||
| range | if true, the type is daterange or datetimerange | `boolean` | false |
|
| range | if true, the type is daterange or datetimerange | `boolean` | false |
|
||||||
| format | format the Date. The parsing tokens are similar to the moment.js | [token](https://github.com/taylorhakes/fecha#formatting-tokens) | 'YYYY-MM-DD' |
|
| format | format the Date. The parsing tokens are similar to the moment.js | [token](https://github.com/taylorhakes/fecha#formatting-tokens) \| [`object`](https://github.com/mengxiong10/vue2-datepicker/issues/232#issuecomment-458558141) | 'YYYY-MM-DD' |
|
||||||
| value-type | type of binding value. If not specified, the binding value will be a Date object | [value-type](#value-type) | 'date' |
|
| value-type | type of binding value. If not specified, the binding value will be a Date object | [value-type](#value-type) | 'date' |
|
||||||
| lang | Translation | [lang](#lang) | 'zh' |
|
| lang | Translation | [lang](#lang) | 'zh' |
|
||||||
| clearable | if false, don't show the clear icon | `boolean` | true |
|
| clearable | if false, don't show the clear icon | `boolean` | true |
|
||||||
|
|||||||
+1
-1
@@ -85,7 +85,7 @@ export default {
|
|||||||
|------|--------------|-------|---------|
|
|------|--------------|-------|---------|
|
||||||
| type | 选择日期类型 | 'date' \| 'datetime' \| 'year' \| 'month' \| 'time' | 'date' |
|
| type | 选择日期类型 | 'date' \| 'datetime' \| 'year' \| 'month' \| 'time' | 'date' |
|
||||||
| range | 如果是true, 显示日历范围选择 | `boolean` | false |
|
| range | 如果是true, 显示日历范围选择 | `boolean` | false |
|
||||||
| format | 格式化显示日期, 值类似moment.js | [token](https://github.com/taylorhakes/fecha#formatting-tokens) | 'YYYY-MM-DD' |
|
| format | 格式化显示日期, 值类似moment.js | [token](https://github.com/taylorhakes/fecha#formatting-tokens) \| [`object`](https://github.com/mengxiong10/vue2-datepicker/issues/232#issuecomment-458558141) | 'YYYY-MM-DD' |
|
||||||
| value-type | 设置绑定值的格式, 默认返回日期对象 | [value-type](#value-type) | 'date' |
|
| value-type | 设置绑定值的格式, 默认返回日期对象 | [value-type](#value-type) | 'date' |
|
||||||
| lang | 选择语言或自定义 | [lang](#lang) | 'zh' |
|
| lang | 选择语言或自定义 | [lang](#lang) | 'zh' |
|
||||||
| clearable | 如果设置false, 不显示清除图标 | `boolean` | true |
|
| clearable | 如果设置false, 不显示清除图标 | `boolean` | true |
|
||||||
|
|||||||
+53
-21
@@ -110,8 +110,8 @@
|
|||||||
<script>
|
<script>
|
||||||
import fecha from 'fecha'
|
import fecha from 'fecha'
|
||||||
import clickoutside from '@/directives/clickoutside'
|
import clickoutside from '@/directives/clickoutside'
|
||||||
import { isValidDate, isValidRange, isDateObejct, isPlainObject, formatDate, parseDate, throttle } from '@/utils/index'
|
import { isValidDate, isValidRangeDate, isDateObejct, isPlainObject, formatDate, parseDate, throttle } from '@/utils/index'
|
||||||
import { transformDate, transformDateRange } from '@/utils/transform'
|
import { transformDate } from '@/utils/transform'
|
||||||
import CalendarPanel from './calendar.vue'
|
import CalendarPanel from './calendar.vue'
|
||||||
import locale from '@/mixins/locale'
|
import locale from '@/mixins/locale'
|
||||||
import Languages from '@/locale/languages'
|
import Languages from '@/locale/languages'
|
||||||
@@ -141,7 +141,7 @@ export default {
|
|||||||
default: 'zh'
|
default: 'zh'
|
||||||
},
|
},
|
||||||
format: {
|
format: {
|
||||||
type: String,
|
type: [String, Object],
|
||||||
default: 'YYYY-MM-DD'
|
default: 'YYYY-MM-DD'
|
||||||
},
|
},
|
||||||
dateFormat: {
|
dateFormat: {
|
||||||
@@ -227,12 +227,17 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
transform () {
|
transform () {
|
||||||
const obj = this.range ? transformDateRange : transformDate
|
|
||||||
const type = this.valueType
|
const type = this.valueType
|
||||||
if (isPlainObject(type)) {
|
if (isPlainObject(type)) {
|
||||||
return { ...obj.date, ...type }
|
return { ...transformDate.date, ...type }
|
||||||
}
|
}
|
||||||
return obj[type] || obj.date
|
if (type === 'format') {
|
||||||
|
return {
|
||||||
|
value2date: this.parse.bind(this),
|
||||||
|
date2value: this.stringify.bind(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return transformDate[type] || transformDate.date
|
||||||
},
|
},
|
||||||
language () {
|
language () {
|
||||||
if (isPlainObject(this.lang)) {
|
if (isPlainObject(this.lang)) {
|
||||||
@@ -250,12 +255,14 @@ export default {
|
|||||||
if (this.userInput !== null) {
|
if (this.userInput !== null) {
|
||||||
return this.userInput
|
return this.userInput
|
||||||
}
|
}
|
||||||
const date = this.transform.value2date(this.value, this.format)
|
const { value2date } = this.transform
|
||||||
if (!this.range) {
|
if (!this.range) {
|
||||||
return date ? this.stringify(date) : ''
|
return this.isValidValue(this.value)
|
||||||
|
? this.stringify(value2date(this.value))
|
||||||
|
: ''
|
||||||
}
|
}
|
||||||
return Array.isArray(date) && date[0] && date[1]
|
return this.isValidRangeValue(this.value)
|
||||||
? `${this.stringify(date[0])} ${this.rangeSeparator} ${this.stringify(date[1])}`
|
? `${this.stringify(value2date(this.value[0]))} ${this.rangeSeparator} ${this.stringify(value2date(this.value[1]))}`
|
||||||
: ''
|
: ''
|
||||||
},
|
},
|
||||||
computedWidth () {
|
computedWidth () {
|
||||||
@@ -265,7 +272,7 @@ export default {
|
|||||||
return this.width
|
return this.width
|
||||||
},
|
},
|
||||||
showClearIcon () {
|
showClearIcon () {
|
||||||
return !this.disabled && this.clearable && (this.range ? isValidRange(this.value) : isValidDate(this.value))
|
return !this.disabled && this.clearable && (this.range ? this.isValidRangeValue(this.value) : this.isValidValue(this.value))
|
||||||
},
|
},
|
||||||
innerType () {
|
innerType () {
|
||||||
return String(this.type).toLowerCase()
|
return String(this.type).toLowerCase()
|
||||||
@@ -314,6 +321,9 @@ export default {
|
|||||||
if (this.dateFormat) {
|
if (this.dateFormat) {
|
||||||
return this.dateFormat
|
return this.dateFormat
|
||||||
}
|
}
|
||||||
|
if (typeof this.format !== 'string') {
|
||||||
|
return 'YYYY-MM-DD'
|
||||||
|
}
|
||||||
if (this.innerType === 'date') {
|
if (this.innerType === 'date') {
|
||||||
return this.format
|
return this.format
|
||||||
}
|
}
|
||||||
@@ -348,11 +358,24 @@ export default {
|
|||||||
this.handleValueChange(this.value)
|
this.handleValueChange(this.value)
|
||||||
this.displayPopup()
|
this.displayPopup()
|
||||||
},
|
},
|
||||||
stringify (date, format) {
|
stringify (date) {
|
||||||
return formatDate(date, format || this.format)
|
return (isPlainObject(this.format) && typeof this.format.stringify === 'function')
|
||||||
|
? this.format.stringify(date)
|
||||||
|
: formatDate(date, this.format)
|
||||||
},
|
},
|
||||||
parseDate (value, format) {
|
parse (value) {
|
||||||
return parseDate(value, format || this.format)
|
return (isPlainObject(this.format) && typeof this.format.parse === 'function')
|
||||||
|
? this.format.parse(value)
|
||||||
|
: parseDate(value, this.format)
|
||||||
|
},
|
||||||
|
isValidValue (value) {
|
||||||
|
const { value2date } = this.transform
|
||||||
|
return isValidDate(value2date(value))
|
||||||
|
},
|
||||||
|
isValidRangeValue (value) {
|
||||||
|
const { value2date } = this.transform
|
||||||
|
return Array.isArray(value) && value.length === 2 && this.isValidValue(value[0]) &&
|
||||||
|
this.isValidValue(value[1]) && (value2date(value[1]).getTime() >= value2date(value[0]).getTime())
|
||||||
},
|
},
|
||||||
dateEqual (a, b) {
|
dateEqual (a, b) {
|
||||||
return isDateObejct(a) && isDateObejct(b) && a.getTime() === b.getTime()
|
return isDateObejct(a) && isDateObejct(b) && a.getTime() === b.getTime()
|
||||||
@@ -374,7 +397,7 @@ export default {
|
|||||||
this.$emit('clear')
|
this.$emit('clear')
|
||||||
},
|
},
|
||||||
confirmDate () {
|
confirmDate () {
|
||||||
const valid = this.range ? isValidRange(this.currentValue) : isValidDate(this.currentValue)
|
const valid = this.range ? isValidRangeDate(this.currentValue) : isValidDate(this.currentValue)
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this.updateDate(true)
|
this.updateDate(true)
|
||||||
}
|
}
|
||||||
@@ -394,10 +417,19 @@ export default {
|
|||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
emitDate (eventName) {
|
emitDate (eventName) {
|
||||||
this.$emit(eventName, this.transform.date2value(this.currentValue, this.format))
|
const { date2value } = this.transform
|
||||||
|
const value = this.range
|
||||||
|
? this.currentValue.map(date2value)
|
||||||
|
: date2value(this.currentValue)
|
||||||
|
this.$emit(eventName, value)
|
||||||
},
|
},
|
||||||
handleValueChange (value) {
|
handleValueChange (value) {
|
||||||
this.currentValue = this.transform.value2date(value, this.format)
|
const { value2date } = this.transform
|
||||||
|
if (this.range) {
|
||||||
|
this.currentValue = this.isValidRangeValue(value) ? value.map(value2date) : [null, null]
|
||||||
|
} else {
|
||||||
|
this.currentValue = this.isValidValue(value) ? value2date(value) : null
|
||||||
|
}
|
||||||
},
|
},
|
||||||
selectDate (date) {
|
selectDate (date) {
|
||||||
this.currentValue = date
|
this.currentValue = date
|
||||||
@@ -497,8 +529,8 @@ export default {
|
|||||||
if (this.range) {
|
if (this.range) {
|
||||||
const range = value.split(` ${this.rangeSeparator} `)
|
const range = value.split(` ${this.rangeSeparator} `)
|
||||||
if (range.length === 2) {
|
if (range.length === 2) {
|
||||||
const start = this.parseDate(range[0], this.format)
|
const start = this.parse(range[0])
|
||||||
const end = this.parseDate(range[1], this.format)
|
const end = this.parse(range[1])
|
||||||
if (start && end && !checkDate(start, null, end) && !checkDate(end, start, null)) {
|
if (start && end && !checkDate(start, null, end) && !checkDate(end, start, null)) {
|
||||||
this.currentValue = [start, end]
|
this.currentValue = [start, end]
|
||||||
this.updateDate(true)
|
this.updateDate(true)
|
||||||
@@ -507,7 +539,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const date = this.parseDate(value, this.format)
|
const date = this.parse(value)
|
||||||
if (date && !checkDate(date, null, null)) {
|
if (date && !checkDate(date, null, null)) {
|
||||||
this.currentValue = date
|
this.currentValue = date
|
||||||
this.updateDate(true)
|
this.updateDate(true)
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ export function isValidDate (date) {
|
|||||||
return !isNaN(new Date(date).getTime())
|
return !isNaN(new Date(date).getTime())
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isValidRange (date) {
|
export function isValidRangeDate (date) {
|
||||||
return (
|
return (
|
||||||
Array.isArray(date) &&
|
Array.isArray(date) &&
|
||||||
date.length === 2 &&
|
date.length === 2 &&
|
||||||
|
|||||||
+2
-30
@@ -1,4 +1,4 @@
|
|||||||
import { isValidDate, isValidRange, parseDate, formatDate } from './index'
|
import { isValidDate } from './index'
|
||||||
|
|
||||||
export const transformDate = {
|
export const transformDate = {
|
||||||
date: {
|
date: {
|
||||||
@@ -7,34 +7,6 @@ export const transformDate = {
|
|||||||
},
|
},
|
||||||
timestamp: {
|
timestamp: {
|
||||||
value2date: (value) => isValidDate(value) ? new Date(value) : null,
|
value2date: (value) => isValidDate(value) ? new Date(value) : null,
|
||||||
date2value: (date) => isValidDate(date) ? new Date(date).getTime() : null
|
date2value: (date) => date && new Date(date).getTime()
|
||||||
},
|
|
||||||
format: {
|
|
||||||
value2date: parseDate,
|
|
||||||
date2value: (date, format) => isValidDate(date) ? formatDate(date, format) : null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const transformDateRange = {
|
|
||||||
date: {
|
|
||||||
value2date: (value) => isValidRange(value) ? [new Date(value[0]), new Date(value[1])] : [null, null],
|
|
||||||
date2value: (date) => date
|
|
||||||
},
|
|
||||||
timestamp: {
|
|
||||||
value2date: (value) => isValidRange(value) ? [new Date(value[0]), new Date(value[1])] : [null, null],
|
|
||||||
date2value: (date) => date.map(transformDate.timestamp.date2value)
|
|
||||||
},
|
|
||||||
format: {
|
|
||||||
value2date: (value, format) => {
|
|
||||||
if (Array.isArray(value) && value.length === 2) {
|
|
||||||
const value0 = parseDate(value[0], format)
|
|
||||||
const value1 = parseDate(value[1], format)
|
|
||||||
if (value0 && value1 && value1 >= value0) {
|
|
||||||
return [value0, value1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return [null, null]
|
|
||||||
},
|
|
||||||
date2value: (date, format) => date.map(v => transformDate.format.date2value(v, format))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-10
@@ -5,7 +5,7 @@ import CalendarPanel from '../src/calendar.vue'
|
|||||||
import DatePanel from '../src/panel/date'
|
import DatePanel from '../src/panel/date'
|
||||||
import TimePanel from '../src/panel/time'
|
import TimePanel from '../src/panel/time'
|
||||||
import YearPanel from '../src/panel/year'
|
import YearPanel from '../src/panel/year'
|
||||||
import { transformDate, transformDateRange } from '../src/utils/transform'
|
import { transformDate } from '../src/utils/transform'
|
||||||
|
|
||||||
let wrapper
|
let wrapper
|
||||||
|
|
||||||
@@ -24,15 +24,6 @@ describe('datepicker', () => {
|
|||||||
expect(vm.transform).toBe(transformDate.date)
|
expect(vm.transform).toBe(transformDate.date)
|
||||||
wrapper.setProps({ valueType: 'timestamp' })
|
wrapper.setProps({ valueType: 'timestamp' })
|
||||||
expect(vm.transform).toBe(transformDate.timestamp)
|
expect(vm.transform).toBe(transformDate.timestamp)
|
||||||
wrapper.setProps({ valueType: 'format' })
|
|
||||||
expect(vm.transform).toBe(transformDate.format)
|
|
||||||
|
|
||||||
wrapper.setProps({ valueType: 'date', range: true })
|
|
||||||
expect(vm.transform).toBe(transformDateRange.date)
|
|
||||||
wrapper.setProps({ valueType: 'timestamp' })
|
|
||||||
expect(vm.transform).toBe(transformDateRange.timestamp)
|
|
||||||
wrapper.setProps({ valueType: 'format' })
|
|
||||||
expect(vm.transform).toBe(transformDateRange.format)
|
|
||||||
|
|
||||||
const fn = (date) => date
|
const fn = (date) => date
|
||||||
wrapper.setProps({ valueType: {
|
wrapper.setProps({ valueType: {
|
||||||
|
|||||||
+7
-18
@@ -1,29 +1,18 @@
|
|||||||
import { transformDate, transformDateRange } from '../src/utils/transform'
|
import { transformDate } from '../src/utils/transform'
|
||||||
|
|
||||||
const time = new Date(2019, 1, 3)
|
const time = new Date(2019, 1, 3)
|
||||||
const timestamp = time.getTime()
|
const timestamp = time.getTime()
|
||||||
const format = 'MM-DD-YYYY'
|
|
||||||
const text = '02-03-2019'
|
|
||||||
|
|
||||||
const testfn = ({ type, value, date, err = null, range = false }) => it(`${type}}`, () => {
|
const testfn = ({ type, value, date, err = null }) => it(`${type}}`, () => {
|
||||||
const obj = range ? transformDateRange : transformDate
|
const obj = transformDate
|
||||||
const typeObj = obj[type]
|
const typeObj = obj[type]
|
||||||
expect(typeObj.value2date(err, format)).toEqual(err)
|
expect(typeObj.value2date(err)).toEqual(err)
|
||||||
expect(typeObj.value2date(value, format)).toEqual(date)
|
expect(typeObj.value2date(value)).toEqual(date)
|
||||||
expect(typeObj.date2value(err, format)).toEqual(err)
|
expect(typeObj.date2value(err)).toEqual(err)
|
||||||
expect(typeObj.date2value(date, format)).toEqual(value)
|
expect(typeObj.date2value(date)).toEqual(value)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('transformDate', () => {
|
describe('transformDate', () => {
|
||||||
testfn({ type: 'date', value: time, date: time })
|
testfn({ type: 'date', value: time, date: time })
|
||||||
testfn({ type: 'format', value: text, date: time })
|
|
||||||
testfn({ type: 'timestamp', value: timestamp, date: time })
|
testfn({ type: 'timestamp', value: timestamp, date: time })
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('transformDateRange', () => {
|
|
||||||
const err = [null, null]
|
|
||||||
const date = [time, time]
|
|
||||||
testfn({ type: 'date', value: [time, time], date, err, range: true })
|
|
||||||
testfn({ type: 'format', value: [text, text], date, err, range: true })
|
|
||||||
testfn({ type: 'timestamp', value: [timestamp, timestamp], date, err, range: true })
|
|
||||||
})
|
|
||||||
|
|||||||
Reference in New Issue
Block a user