ant-design-vue/components/input/TextArea.jsx

187 lines
4.5 KiB
Vue
Raw Normal View History

2019-04-07 09:19:18 +00:00
import classNames from 'classnames';
2019-01-12 03:33:27 +00:00
import omit from 'omit.js';
import ResizeObserver from 'resize-observer-polyfill';
import inputProps from './inputProps';
import calculateNodeHeight from './calculateNodeHeight';
import hasProp from '../_util/props-util';
2019-04-07 09:19:18 +00:00
import { ConfigConsumerProps } from '../config-provider';
2018-03-19 02:16:27 +00:00
2019-01-12 03:33:27 +00:00
function onNextFrame(cb) {
2017-12-07 04:31:12 +00:00
if (window.requestAnimationFrame) {
2019-01-12 03:33:27 +00:00
return window.requestAnimationFrame(cb);
2017-12-07 04:31:12 +00:00
}
2019-01-12 03:33:27 +00:00
return window.setTimeout(cb, 1);
2017-12-07 04:31:12 +00:00
}
2019-01-12 03:33:27 +00:00
function clearNextFrameAction(nextFrameId) {
2017-12-07 04:31:12 +00:00
if (window.cancelAnimationFrame) {
2019-01-12 03:33:27 +00:00
window.cancelAnimationFrame(nextFrameId);
2017-12-07 04:31:12 +00:00
} else {
2019-01-12 03:33:27 +00:00
window.clearTimeout(nextFrameId);
2017-12-07 04:31:12 +00:00
}
}
2019-01-12 03:33:27 +00:00
function fixControlledValue(value) {
2017-12-07 04:31:12 +00:00
if (typeof value === 'undefined' || value === null) {
2019-01-12 03:33:27 +00:00
return '';
2017-12-07 04:31:12 +00:00
}
2019-01-12 03:33:27 +00:00
return value;
2017-12-07 04:31:12 +00:00
}
2019-01-12 03:33:27 +00:00
function noop() {}
2017-12-07 04:31:12 +00:00
export default {
2018-04-08 13:17:20 +00:00
name: 'ATextarea',
2017-12-07 04:31:12 +00:00
model: {
prop: 'value',
event: 'change.value',
},
2019-02-01 09:23:00 +00:00
props: {
...inputProps,
autosize: [Object, Boolean],
},
2019-04-07 09:19:18 +00:00
inject: {
2019-09-11 14:35:25 +00:00
configProvider: { default: () => ConfigConsumerProps },
2019-04-07 09:19:18 +00:00
},
2019-01-12 03:33:27 +00:00
data() {
const { value = '', defaultValue = '' } = this.$props;
2017-12-07 04:31:12 +00:00
return {
2017-12-27 10:15:11 +00:00
stateValue: fixControlledValue(!hasProp(this, 'value') ? defaultValue : value),
2017-12-07 04:31:12 +00:00
nextFrameActionId: undefined,
textareaStyles: {},
2019-01-12 03:33:27 +00:00
};
2017-12-07 04:31:12 +00:00
},
2019-01-12 03:33:27 +00:00
computed: {},
2017-12-07 04:31:12 +00:00
watch: {
2019-01-12 03:33:27 +00:00
value(val) {
2019-01-03 12:51:56 +00:00
this.$nextTick(() => {
2019-01-12 03:33:27 +00:00
this.resizeOnNextFrame();
});
this.stateValue = fixControlledValue(val);
2019-01-03 12:51:56 +00:00
},
2019-01-12 03:33:27 +00:00
autosize(val) {
2019-01-03 12:51:56 +00:00
if (!val && this.$refs.textArea) {
2019-01-12 03:33:27 +00:00
this.textareaStyles = omit(this.textareaStyles, ['overflowY']);
2017-12-07 04:31:12 +00:00
}
},
},
2019-01-12 03:33:27 +00:00
mounted() {
2018-06-10 02:26:03 +00:00
this.$nextTick(() => {
2019-01-12 03:33:27 +00:00
this.resizeTextarea();
this.updateResizeObserverHook();
2018-06-10 02:26:03 +00:00
if (this.autoFocus) {
2019-01-12 03:33:27 +00:00
this.focus();
2018-06-10 02:26:03 +00:00
}
2019-01-12 03:33:27 +00:00
});
2017-12-07 04:31:12 +00:00
},
2019-01-12 03:33:27 +00:00
updated() {
this.updateResizeObserverHook();
2019-01-03 12:51:56 +00:00
},
2019-01-12 03:33:27 +00:00
beforeDestroy() {
2019-01-03 12:51:56 +00:00
if (this.resizeObserver) {
2019-01-12 03:33:27 +00:00
this.resizeObserver.disconnect();
2019-01-03 12:51:56 +00:00
}
},
2017-12-07 04:31:12 +00:00
methods: {
2019-01-12 03:33:27 +00:00
resizeOnNextFrame() {
2019-01-03 12:51:56 +00:00
if (this.nextFrameActionId) {
2019-01-12 03:33:27 +00:00
clearNextFrameAction(this.nextFrameActionId);
2019-01-03 12:51:56 +00:00
}
2019-01-12 03:33:27 +00:00
this.nextFrameActionId = onNextFrame(this.resizeTextarea);
2019-01-03 12:51:56 +00:00
},
// We will update hooks if `autosize` prop change
2019-01-12 03:33:27 +00:00
updateResizeObserverHook() {
2019-01-03 12:51:56 +00:00
if (!this.resizeObserver && this.$props.autosize) {
// Add resize observer
2019-01-12 03:33:27 +00:00
this.resizeObserver = new ResizeObserver(this.resizeOnNextFrame);
this.resizeObserver.observe(this.$refs.textArea);
2019-01-03 12:51:56 +00:00
} else if (this.resizeObserver && !this.$props.autosize) {
// Remove resize observer
2019-01-12 03:33:27 +00:00
this.resizeObserver.disconnect();
this.resizeObserver = null;
2019-01-03 12:51:56 +00:00
}
},
2019-01-12 03:33:27 +00:00
handleKeyDown(e) {
2017-12-07 04:31:12 +00:00
if (e.keyCode === 13) {
2019-01-12 03:33:27 +00:00
this.$emit('pressEnter', e);
2017-12-07 04:31:12 +00:00
}
2019-01-12 03:33:27 +00:00
this.$emit('keydown', e);
2017-12-07 04:31:12 +00:00
},
2019-01-12 03:33:27 +00:00
resizeTextarea() {
const { autosize } = this.$props;
2017-12-07 04:31:12 +00:00
if (!autosize || !this.$refs.textArea) {
2019-01-12 03:33:27 +00:00
return;
2017-12-07 04:31:12 +00:00
}
2019-04-07 09:19:18 +00:00
const { minRows, maxRows } = autosize;
2019-01-12 03:33:27 +00:00
const textareaStyles = calculateNodeHeight(this.$refs.textArea, false, minRows, maxRows);
this.textareaStyles = textareaStyles;
2017-12-07 04:31:12 +00:00
},
2019-01-12 03:33:27 +00:00
handleTextareaChange(e) {
const { value, composing } = e.target;
if (composing || this.stateValue === value) return;
2017-12-27 10:15:11 +00:00
if (!hasProp(this, 'value')) {
this.stateValue = value;
2019-01-12 03:33:27 +00:00
this.resizeTextarea();
2017-12-07 04:31:12 +00:00
} else {
2019-01-12 03:33:27 +00:00
this.$forceUpdate();
}
this.$emit('change.value', value);
2019-01-12 03:33:27 +00:00
this.$emit('change', e);
this.$emit('input', e);
2017-12-07 04:31:12 +00:00
},
2019-01-12 03:33:27 +00:00
focus() {
this.$refs.textArea.focus();
2017-12-07 04:31:12 +00:00
},
2019-01-12 03:33:27 +00:00
blur() {
this.$refs.textArea.blur();
2017-12-07 04:31:12 +00:00
},
},
2019-01-12 03:33:27 +00:00
render() {
const {
stateValue,
2018-02-28 11:07:04 +00:00
handleKeyDown,
handleTextareaChange,
textareaStyles,
$attrs,
$listeners,
2019-04-07 09:19:18 +00:00
prefixCls: customizePrefixCls,
disabled,
2019-01-12 03:33:27 +00:00
} = this;
2017-12-07 04:31:12 +00:00
const otherProps = omit(this.$props, [
'prefixCls',
'autosize',
'type',
2019-01-03 12:51:56 +00:00
'value',
'defaultValue',
2019-01-12 03:33:27 +00:00
]);
2019-09-11 14:35:25 +00:00
const getPrefixCls = this.configProvider.getPrefixCls;
2019-04-07 09:19:18 +00:00
const prefixCls = getPrefixCls('input', customizePrefixCls);
const cls = classNames(prefixCls, {
[`${prefixCls}-disabled`]: disabled,
});
2018-02-28 11:07:04 +00:00
const textareaProps = {
directives: [{ name: 'ant-input' }],
2018-02-28 11:07:04 +00:00
attrs: { ...otherProps, ...$attrs },
on: {
...$listeners,
keydown: handleKeyDown,
input: handleTextareaChange,
change: noop,
2018-02-28 11:07:04 +00:00
},
2019-01-12 03:33:27 +00:00
};
2017-12-07 04:31:12 +00:00
return (
<textarea
2018-02-28 11:07:04 +00:00
{...textareaProps}
2017-12-07 04:31:12 +00:00
value={stateValue}
2019-04-07 09:19:18 +00:00
class={cls}
2017-12-07 04:31:12 +00:00
style={textareaStyles}
2019-01-12 03:33:27 +00:00
ref="textArea"
2017-12-07 04:31:12 +00:00
/>
2019-01-12 03:33:27 +00:00
);
2017-12-07 04:31:12 +00:00
},
2019-01-12 03:33:27 +00:00
};