123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956 |
- <template>
- <el-input
- class="el-date-editor"
- :class="'el-date-editor--' + type"
- :readonly="!editable || readonly || type === 'dates' || type === 'week' || type === 'years' || type === 'months'"
- :disabled="pickerDisabled"
- :size="pickerSize"
- :name="name"
- v-bind="firstInputId"
- v-if="!ranged"
- v-clickoutside="handleClose"
- :placeholder="placeholder"
- @focus="handleFocus"
- @keydown.native="handleKeydown"
- :value="displayValue"
- @input="value => userInput = value"
- @change="handleChange"
- @mouseenter.native="handleMouseEnter"
- @mouseleave.native="showClose = false"
- :validateEvent="false"
- ref="reference">
- <i slot="prefix"
- class="el-input__icon"
- :class="triggerClass"
- @click="handleFocus">
- </i>
- <i slot="suffix"
- class="el-input__icon"
- @click="handleClickIcon"
- :class="[showClose ? '' + clearIcon : '']"
- v-if="haveTrigger">
- </i>
- </el-input>
- <div
- class="el-date-editor el-range-editor el-input__inner"
- :class="[
- 'el-date-editor--' + type,
- pickerSize ? `el-range-editor--${ pickerSize }` : '',
- pickerDisabled ? 'is-disabled' : '',
- pickerVisible ? 'is-active' : ''
- ]"
- @click="handleRangeClick"
- @mouseenter="handleMouseEnter"
- @mouseleave="showClose = false"
- @keydown="handleKeydown"
- ref="reference"
- v-clickoutside="handleClose"
- v-else>
- <i :class="['el-input__icon', 'el-range__icon', triggerClass]"></i>
- <input
- autocomplete="off"
- :placeholder="startPlaceholder"
- :value="displayValue && displayValue[0]"
- :disabled="pickerDisabled"
- v-bind="firstInputId"
- :readonly="!editable || readonly"
- :name="name && name[0]"
- @input="handleStartInput"
- @change="handleStartChange"
- @focus="handleFocus"
- class="el-range-input">
- <slot name="range-separator">
- <span class="el-range-separator">{{ rangeSeparator }}</span>
- </slot>
- <input
- autocomplete="off"
- :placeholder="endPlaceholder"
- :value="displayValue && displayValue[1]"
- :disabled="pickerDisabled"
- v-bind="secondInputId"
- :readonly="!editable || readonly"
- :name="name && name[1]"
- @input="handleEndInput"
- @change="handleEndChange"
- @focus="handleFocus"
- class="el-range-input">
- <i
- @click="handleClickIcon"
- v-if="haveTrigger"
- :class="[showClose ? '' + clearIcon : '']"
- class="el-input__icon el-range__close-icon">
- </i>
- </div>
- </template>
- <script>
- import Vue from 'vue';
- import Clickoutside from 'element-ui/src/utils/clickoutside';
- import { formatDate, parseDate, isDateObject, getWeekNumber } from 'element-ui/src/utils/date-util';
- import Popper from 'element-ui/src/utils/vue-popper';
- import Emitter from 'element-ui/src/mixins/emitter';
- import ElInput from 'element-ui/packages/input';
- import merge from 'element-ui/src/utils/merge';
- const NewPopper = {
- props: {
- appendToBody: Popper.props.appendToBody,
- offset: Popper.props.offset,
- boundariesPadding: Popper.props.boundariesPadding,
- arrowOffset: Popper.props.arrowOffset,
- transformOrigin: Popper.props.transformOrigin
- },
- methods: Popper.methods,
- data() {
- return merge({ visibleArrow: true }, Popper.data);
- },
- beforeDestroy: Popper.beforeDestroy
- };
- const DEFAULT_FORMATS = {
- date: 'yyyy-MM-dd',
- month: 'yyyy-MM',
- months: 'yyyy-MM',
- datetime: 'yyyy-MM-dd HH:mm:ss',
- time: 'HH:mm:ss',
- week: 'yyyywWW',
- timerange: 'HH:mm:ss',
- daterange: 'yyyy-MM-dd',
- monthrange: 'yyyy-MM',
- datetimerange: 'yyyy-MM-dd HH:mm:ss',
- year: 'yyyy',
- years: 'yyyy'
- };
- const HAVE_TRIGGER_TYPES = [
- 'date',
- 'datetime',
- 'time',
- 'time-select',
- 'week',
- 'month',
- 'year',
- 'daterange',
- 'monthrange',
- 'timerange',
- 'datetimerange',
- 'dates',
- 'months',
- 'years'
- ];
- const DATE_FORMATTER = function(value, format) {
- if (format === 'timestamp') return value.getTime();
- return formatDate(value, format);
- };
- const DATE_PARSER = function(text, format) {
- if (format === 'timestamp') return new Date(Number(text));
- return parseDate(text, format);
- };
- const RANGE_FORMATTER = function(value, format) {
- if (Array.isArray(value) && value.length === 2) {
- const start = value[0];
- const end = value[1];
- if (start && end) {
- return [DATE_FORMATTER(start, format), DATE_FORMATTER(end, format)];
- }
- }
- return '';
- };
- const RANGE_PARSER = function(array, format, separator) {
- if (!Array.isArray(array)) {
- array = array.split(separator);
- }
- if (array.length === 2) {
- const range1 = array[0];
- const range2 = array[1];
- return [DATE_PARSER(range1, format), DATE_PARSER(range2, format)];
- }
- return [];
- };
- const TYPE_VALUE_RESOLVER_MAP = {
- default: {
- formatter(value) {
- if (!value) return '';
- return '' + value;
- },
- parser(text) {
- if (text === undefined || text === '') return null;
- return text;
- }
- },
- week: {
- formatter(value, format) {
- let week = getWeekNumber(value);
- let month = value.getMonth();
- const trueDate = new Date(value);
- if (week === 1 && month === 11) {
- trueDate.setHours(0, 0, 0, 0);
- trueDate.setDate(trueDate.getDate() + 3 - (trueDate.getDay() + 6) % 7);
- }
- let date = formatDate(trueDate, format);
- date = /WW/.test(date)
- ? date.replace(/WW/, week < 10 ? '0' + week : week)
- : date.replace(/W/, week);
- return date;
- },
- parser(text, format) {
- // parse as if a normal date
- return TYPE_VALUE_RESOLVER_MAP.date.parser(text, format);
- }
- },
- date: {
- formatter: DATE_FORMATTER,
- parser: DATE_PARSER
- },
- datetime: {
- formatter: DATE_FORMATTER,
- parser: DATE_PARSER
- },
- daterange: {
- formatter: RANGE_FORMATTER,
- parser: RANGE_PARSER
- },
- monthrange: {
- formatter: RANGE_FORMATTER,
- parser: RANGE_PARSER
- },
- datetimerange: {
- formatter: RANGE_FORMATTER,
- parser: RANGE_PARSER
- },
- timerange: {
- formatter: RANGE_FORMATTER,
- parser: RANGE_PARSER
- },
- time: {
- formatter: DATE_FORMATTER,
- parser: DATE_PARSER
- },
- month: {
- formatter: DATE_FORMATTER,
- parser: DATE_PARSER
- },
- year: {
- formatter: DATE_FORMATTER,
- parser: DATE_PARSER
- },
- number: {
- formatter(value) {
- if (!value) return '';
- return '' + value;
- },
- parser(text) {
- let result = Number(text);
- if (!isNaN(text)) {
- return result;
- } else {
- return null;
- }
- }
- },
- dates: {
- formatter(value, format) {
- return value.map(date => DATE_FORMATTER(date, format));
- },
- parser(value, format) {
- return (typeof value === 'string' ? value.split(', ') : value)
- .map(date => date instanceof Date ? date : DATE_PARSER(date, format));
- }
- },
- months: {
- formatter(value, format) {
- return value.map(date => DATE_FORMATTER(date, format));
- },
- parser(value, format) {
- return (typeof value === 'string' ? value.split(', ') : value)
- .map(date => date instanceof Date ? date : DATE_PARSER(date, format));
- }
- },
- years: {
- formatter(value, format) {
- return value.map(date => DATE_FORMATTER(date, format));
- },
- parser(value, format) {
- return (typeof value === 'string' ? value.split(', ') : value)
- .map(date => date instanceof Date ? date : DATE_PARSER(date, format));
- }
- }
- };
- const PLACEMENT_MAP = {
- left: 'bottom-start',
- center: 'bottom',
- right: 'bottom-end'
- };
- const parseAsFormatAndType = (value, customFormat, type, rangeSeparator = '-') => {
- if (!value) return null;
- const parser = (
- TYPE_VALUE_RESOLVER_MAP[type] ||
- TYPE_VALUE_RESOLVER_MAP['default']
- ).parser;
- const format = customFormat || DEFAULT_FORMATS[type];
- return parser(value, format, rangeSeparator);
- };
- const formatAsFormatAndType = (value, customFormat, type) => {
- if (!value) return null;
- const formatter = (
- TYPE_VALUE_RESOLVER_MAP[type] ||
- TYPE_VALUE_RESOLVER_MAP['default']
- ).formatter;
- const format = customFormat || DEFAULT_FORMATS[type];
- return formatter(value, format);
- };
- /*
- * Considers:
- * 1. Date object
- * 2. date string
- * 3. array of 1 or 2
- */
- const valueEquals = function(a, b) {
- // considers Date object and string
- const dateEquals = function(a, b) {
- const aIsDate = a instanceof Date;
- const bIsDate = b instanceof Date;
- if (aIsDate && bIsDate) {
- return a.getTime() === b.getTime();
- }
- if (!aIsDate && !bIsDate) {
- return a === b;
- }
- return false;
- };
- const aIsArray = a instanceof Array;
- const bIsArray = b instanceof Array;
- if (aIsArray && bIsArray) {
- if (a.length !== b.length) {
- return false;
- }
- return a.every((item, index) => dateEquals(item, b[index]));
- }
- if (!aIsArray && !bIsArray) {
- return dateEquals(a, b);
- }
- return false;
- };
- const isString = function(val) {
- return typeof val === 'string' || val instanceof String;
- };
- const validator = function(val) {
- // either: String, Array of String, null / undefined
- return (
- val === null ||
- val === undefined ||
- isString(val) ||
- (Array.isArray(val) && val.length === 2 && val.every(isString))
- );
- };
- export default {
- mixins: [Emitter, NewPopper],
- inject: {
- elForm: {
- default: ''
- },
- elFormItem: {
- default: ''
- }
- },
- props: {
- size: String,
- format: String,
- valueFormat: String,
- readonly: Boolean,
- placeholder: String,
- startPlaceholder: String,
- endPlaceholder: String,
- prefixIcon: String,
- clearIcon: {
- type: String,
- default: 'el-icon-circle-close'
- },
- name: {
- default: '',
- validator
- },
- disabled: Boolean,
- clearable: {
- type: Boolean,
- default: true
- },
- id: {
- default: '',
- validator
- },
- popperClass: String,
- editable: {
- type: Boolean,
- default: true
- },
- align: {
- type: String,
- default: 'left'
- },
- value: {},
- defaultValue: {},
- defaultTime: {},
- rangeSeparator: {
- default: '-'
- },
- pickerOptions: {},
- unlinkPanels: Boolean,
- validateEvent: {
- type: Boolean,
- default: true
- }
- },
- components: { ElInput },
- directives: { Clickoutside },
- data() {
- return {
- pickerVisible: false,
- showClose: false,
- userInput: null,
- valueOnOpen: null, // value when picker opens, used to determine whether to emit change
- unwatchPickerOptions: null
- };
- },
- watch: {
- pickerVisible(val) {
- if (this.readonly || this.pickerDisabled) return;
- if (val) {
- this.showPicker();
- this.valueOnOpen = Array.isArray(this.value) ? [...this.value] : this.value;
- } else {
- this.hidePicker();
- this.emitChange(this.value);
- this.userInput = null;
- if (this.validateEvent) {
- this.dispatch('ElFormItem', 'el.form.blur');
- }
- this.$emit('blur', this);
- this.blur();
- }
- },
- parsedValue: {
- immediate: true,
- handler(val) {
- if (this.picker) {
- this.picker.value = val;
- }
- }
- },
- defaultValue(val) {
- // NOTE: should eventually move to jsx style picker + panel ?
- if (this.picker) {
- this.picker.defaultValue = val;
- }
- },
- value(val, oldVal) {
- if (!valueEquals(val, oldVal) && !this.pickerVisible && this.validateEvent) {
- this.dispatch('ElFormItem', 'el.form.change', val);
- }
- }
- },
- computed: {
- ranged() {
- return this.type.indexOf('range') > -1;
- },
- reference() {
- const reference = this.$refs.reference;
- return reference.$el || reference;
- },
- refInput() {
- if (this.reference) {
- return [].slice.call(this.reference.querySelectorAll('input'));
- }
- return [];
- },
- valueIsEmpty() {
- const val = this.value;
- if (Array.isArray(val)) {
- for (let i = 0, len = val.length; i < len; i++) {
- if (val[i]) {
- return false;
- }
- }
- } else {
- if (val) {
- return false;
- }
- }
- return true;
- },
- triggerClass() {
- return this.prefixIcon || (this.type.indexOf('time') !== -1 ? 'el-icon-time' : 'el-icon-date');
- },
- selectionMode() {
- if (this.type === 'week') {
- return 'week';
- } else if (this.type === 'month') {
- return 'month';
- } else if (this.type === 'year') {
- return 'year';
- } else if (this.type === 'dates') {
- return 'dates';
- } else if (this.type === 'months') {
- return 'months';
- } else if (this.type === 'years') {
- return 'years';
- }
- return 'day';
- },
- haveTrigger() {
- if (typeof this.showTrigger !== 'undefined') {
- return this.showTrigger;
- }
- return HAVE_TRIGGER_TYPES.indexOf(this.type) !== -1;
- },
- displayValue() {
- const formattedValue = formatAsFormatAndType(this.parsedValue, this.format, this.type, this.rangeSeparator);
- if (Array.isArray(this.userInput)) {
- return [
- this.userInput[0] || (formattedValue && formattedValue[0]) || '',
- this.userInput[1] || (formattedValue && formattedValue[1]) || ''
- ];
- } else if (this.userInput !== null) {
- return this.userInput;
- } else if (formattedValue) {
- return (this.type === 'dates' || this.type === 'years' || this.type === 'months')
- ? formattedValue.join(', ')
- : formattedValue;
- } else {
- return '';
- }
- },
- parsedValue() {
- if (!this.value) return this.value; // component value is not set
- if (this.type === 'time-select') return this.value; // time-select does not require parsing, this might change in next major version
- const valueIsDateObject = isDateObject(this.value) || (Array.isArray(this.value) && this.value.every(isDateObject));
- if (valueIsDateObject) {
- return this.value;
- }
- if (this.valueFormat) {
- return parseAsFormatAndType(this.value, this.valueFormat, this.type, this.rangeSeparator) || this.value;
- }
- // NOTE: deal with common but incorrect usage, should remove in next major version
- // user might provide string / timestamp without value-format, coerce them into date (or array of date)
- return Array.isArray(this.value) ? this.value.map(val => new Date(val)) : new Date(this.value);
- },
- _elFormItemSize() {
- return (this.elFormItem || {}).elFormItemSize;
- },
- pickerSize() {
- return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
- },
- pickerDisabled() {
- return this.disabled || (this.elForm || {}).disabled;
- },
- firstInputId() {
- const obj = {};
- let id;
- if (this.ranged) {
- id = this.id && this.id[0];
- } else {
- id = this.id;
- }
- if (id) obj.id = id;
- return obj;
- },
- secondInputId() {
- const obj = {};
- let id;
- if (this.ranged) {
- id = this.id && this.id[1];
- }
- if (id) obj.id = id;
- return obj;
- }
- },
- created() {
- // vue-popper
- this.popperOptions = {
- boundariesPadding: 0,
- gpuAcceleration: false
- };
- this.placement = PLACEMENT_MAP[this.align] || PLACEMENT_MAP.left;
- this.$on('fieldReset', this.handleFieldReset);
- },
- methods: {
- focus() {
- if (!this.ranged) {
- this.$refs.reference.focus();
- } else {
- this.handleFocus();
- }
- },
- blur() {
- this.refInput.forEach(input => input.blur());
- },
- // {parse, formatTo} Value deals maps component value with internal Date
- parseValue(value) {
- const isParsed = isDateObject(value) || (Array.isArray(value) && value.every(isDateObject));
- if (this.valueFormat && !isParsed) {
- return parseAsFormatAndType(value, this.valueFormat, this.type, this.rangeSeparator) || value;
- } else {
- return value;
- }
- },
- formatToValue(date) {
- const isFormattable = isDateObject(date) || (Array.isArray(date) && date.every(isDateObject));
- if (this.valueFormat && isFormattable) {
- return formatAsFormatAndType(date, this.valueFormat, this.type, this.rangeSeparator);
- } else {
- return date;
- }
- },
- // {parse, formatTo} String deals with user input
- parseString(value) {
- const type = Array.isArray(value) ? this.type : this.type.replace('range', '');
- return parseAsFormatAndType(value, this.format, type);
- },
- formatToString(value) {
- const type = Array.isArray(value) ? this.type : this.type.replace('range', '');
- return formatAsFormatAndType(value, this.format, type);
- },
- handleMouseEnter() {
- if (this.readonly || this.pickerDisabled) return;
- if (!this.valueIsEmpty && this.clearable) {
- this.showClose = true;
- }
- },
- handleChange() {
- if (this.userInput) {
- const value = this.parseString(this.displayValue);
- if (value) {
- this.picker.value = value;
- if (this.isValidValue(value)) {
- this.emitInput(value);
- this.userInput = null;
- }
- }
- }
- if (this.userInput === '') {
- this.emitInput(null);
- this.emitChange(null);
- this.userInput = null;
- }
- },
- handleStartInput(event) {
- if (this.userInput) {
- this.userInput = [event.target.value, this.userInput[1]];
- } else {
- this.userInput = [event.target.value, null];
- }
- },
- handleEndInput(event) {
- if (this.userInput) {
- this.userInput = [this.userInput[0], event.target.value];
- } else {
- this.userInput = [null, event.target.value];
- }
- },
- handleStartChange(event) {
- const value = this.parseString(this.userInput && this.userInput[0]);
- if (value) {
- this.userInput = [this.formatToString(value), this.displayValue[1]];
- const newValue = [value, this.picker.value && this.picker.value[1]];
- this.picker.value = newValue;
- if (this.isValidValue(newValue)) {
- this.emitInput(newValue);
- this.userInput = null;
- }
- }
- },
- handleEndChange(event) {
- const value = this.parseString(this.userInput && this.userInput[1]);
- if (value) {
- this.userInput = [this.displayValue[0], this.formatToString(value)];
- const newValue = [this.picker.value && this.picker.value[0], value];
- this.picker.value = newValue;
- if (this.isValidValue(newValue)) {
- this.emitInput(newValue);
- this.userInput = null;
- }
- }
- },
- handleClickIcon(event) {
- if (this.readonly || this.pickerDisabled) return;
- if (this.showClose) {
- this.valueOnOpen = this.value;
- event.stopPropagation();
- this.emitInput(null);
- this.emitChange(null);
- this.showClose = false;
- if (this.picker && typeof this.picker.handleClear === 'function') {
- this.picker.handleClear();
- }
- } else {
- this.pickerVisible = !this.pickerVisible;
- }
- },
- handleClose() {
- if (!this.pickerVisible) return;
- this.pickerVisible = false;
- if (this.type === 'dates' || this.type === 'years' || this.type === 'months') {
- // restore to former value
- const oldValue = parseAsFormatAndType(this.valueOnOpen, this.valueFormat, this.type, this.rangeSeparator) || this.valueOnOpen;
- this.emitInput(oldValue);
- }
- },
- handleFieldReset(initialValue) {
- this.userInput = initialValue === '' ? null : initialValue;
- },
- handleFocus() {
- const type = this.type;
- if (HAVE_TRIGGER_TYPES.indexOf(type) !== -1 && !this.pickerVisible) {
- this.pickerVisible = true;
- }
- this.$emit('focus', this);
- },
- handleKeydown(event) {
- const keyCode = event.keyCode;
- // ESC
- if (keyCode === 27) {
- this.pickerVisible = false;
- event.stopPropagation();
- return;
- }
- // Tab
- if (keyCode === 9) {
- if (!this.ranged) {
- this.handleChange();
- this.pickerVisible = this.picker.visible = false;
- this.blur();
- event.stopPropagation();
- } else {
- // user may change focus between two input
- setTimeout(() => {
- if (this.refInput.indexOf(document.activeElement) === -1) {
- this.pickerVisible = false;
- this.blur();
- event.stopPropagation();
- }
- }, 0);
- }
- return;
- }
- // Enter
- if (keyCode === 13) {
- if (this.userInput === '' || this.isValidValue(this.parseString(this.displayValue))) {
- this.handleChange();
- this.pickerVisible = this.picker.visible = false;
- this.blur();
- }
- event.stopPropagation();
- return;
- }
- // if user is typing, do not let picker handle key input
- if (this.userInput) {
- event.stopPropagation();
- return;
- }
- // delegate other keys to panel
- if (this.picker && this.picker.handleKeydown) {
- this.picker.handleKeydown(event);
- }
- },
- handleRangeClick() {
- const type = this.type;
- if (HAVE_TRIGGER_TYPES.indexOf(type) !== -1 && !this.pickerVisible) {
- this.pickerVisible = true;
- }
- this.$emit('focus', this);
- },
- hidePicker() {
- if (this.picker) {
- this.picker.resetView && this.picker.resetView();
- this.pickerVisible = this.picker.visible = false;
- this.destroyPopper();
- }
- },
- showPicker() {
- if (this.$isServer) return;
- if (!this.picker) {
- this.mountPicker();
- }
- this.pickerVisible = this.picker.visible = true;
- this.updatePopper();
- this.picker.value = this.parsedValue;
- this.picker.resetView && this.picker.resetView();
- this.$nextTick(() => {
- this.picker.adjustSpinners && this.picker.adjustSpinners();
- });
- },
- mountPicker() {
- this.picker = new Vue(this.panel).$mount();
- this.picker.defaultValue = this.defaultValue;
- this.picker.defaultTime = this.defaultTime;
- this.picker.popperClass = this.popperClass;
- this.popperElm = this.picker.$el;
- this.picker.width = this.reference.getBoundingClientRect().width;
- this.picker.showTime = this.type === 'datetime' || this.type === 'datetimerange';
- this.picker.selectionMode = this.selectionMode;
- this.picker.unlinkPanels = this.unlinkPanels;
- this.picker.arrowControl = this.arrowControl || this.timeArrowControl || false;
- this.$watch('format', (format) => {
- this.picker.format = format;
- });
- const updateOptions = () => {
- const options = this.pickerOptions;
- if (options && options.selectableRange) {
- let ranges = options.selectableRange;
- const parser = TYPE_VALUE_RESOLVER_MAP.datetimerange.parser;
- const format = DEFAULT_FORMATS.timerange;
- ranges = Array.isArray(ranges) ? ranges : [ranges];
- this.picker.selectableRange = ranges.map(range => parser(range, format, this.rangeSeparator));
- }
- for (const option in options) {
- if (options.hasOwnProperty(option) &&
- // 忽略 time-picker 的该配置项
- option !== 'selectableRange') {
- this.picker[option] = options[option];
- }
- }
- // main format must prevail over undocumented pickerOptions.format
- if (this.format) {
- this.picker.format = this.format;
- }
- };
- updateOptions();
- this.unwatchPickerOptions = this.$watch('pickerOptions', () => updateOptions(), { deep: true });
- this.$el.appendChild(this.picker.$el);
- this.picker.resetView && this.picker.resetView();
- this.picker.$on('dodestroy', this.doDestroy);
- this.picker.$on('pick', (date = '', visible = false) => {
- this.userInput = null;
- this.pickerVisible = this.picker.visible = visible;
- this.emitInput(date);
- this.picker.resetView && this.picker.resetView();
- });
- this.picker.$on('select-range', (start, end, pos) => {
- if (this.refInput.length === 0) return;
- if (!pos || pos === 'min') {
- this.refInput[0].setSelectionRange(start, end);
- this.refInput[0].focus();
- } else if (pos === 'max') {
- this.refInput[1].setSelectionRange(start, end);
- this.refInput[1].focus();
- }
- });
- },
- unmountPicker() {
- if (this.picker) {
- this.picker.$destroy();
- this.picker.$off();
- if (typeof this.unwatchPickerOptions === 'function') {
- this.unwatchPickerOptions();
- }
- this.picker.$el.parentNode.removeChild(this.picker.$el);
- }
- },
- emitChange(val) {
- // determine user real change only
- if (!valueEquals(val, this.valueOnOpen)) {
- this.$emit('change', val);
- this.valueOnOpen = val;
- if (this.validateEvent) {
- this.dispatch('ElFormItem', 'el.form.change', val);
- }
- }
- },
- emitInput(val) {
- const formatted = this.formatToValue(val);
- if (!valueEquals(this.value, formatted)) {
- this.$emit('input', formatted);
- }
- },
- isValidValue(value) {
- if (!this.picker) {
- this.mountPicker();
- }
- if (this.picker.isValidValue) {
- return value && this.picker.isValidValue(value);
- } else {
- return true;
- }
- }
- }
- };
- </script>
|