element-plus/packages/form/src/label-wrap.ts
bastarder ef35578a32
fix(form): fix form-item auto width bug (#830)
Co-authored-by: bastarder <jie.qian@blockheaders.com>
2020-12-04 17:39:17 +08:00

103 lines
2.5 KiB
TypeScript

import {
defineComponent,
h,
inject,
ref,
watch,
onMounted,
onUpdated,
onBeforeUnmount,
nextTick,
Fragment,
} from 'vue'
import {
elFormKey, elFormItemKey,
} from './token'
import {
addResizeListener,
removeResizeListener,
ResizableElement,
} from '@element-plus/utils/resize-event'
export default defineComponent({
name: 'ElLabelWrap',
props: {
isAutoWidth: Boolean,
updateAll: Boolean,
},
setup(props, { slots }) {
const el = ref<Nullable<HTMLElement>>(null)
const elForm = inject(elFormKey)
const elFormItem = inject(elFormItemKey)
const computedWidth = ref(0)
watch(computedWidth, (val, oldVal) => {
if (props.updateAll) {
elForm.registerLabelWidth(val, oldVal)
elFormItem.updateComputedLabelWidth(val)
}
})
const getLabelWidth = () => {
if (el.value?.firstElementChild) {
const width = window.getComputedStyle(el.value.firstElementChild)
.width
return Math.ceil(parseFloat(width))
} else {
return 0
}
}
const updateLabelWidth = (action = 'update') => {
nextTick(() => {
if (slots.default && props.isAutoWidth) {
if (action === 'update') {
computedWidth.value = getLabelWidth()
} else if (action === 'remove') {
elForm.deregisterLabelWidth(computedWidth.value)
}
}
})
}
const updateLabelWidthFn = () => updateLabelWidth('update')
onMounted(() => {
addResizeListener(el.value.firstElementChild as ResizableElement, updateLabelWidthFn)
updateLabelWidthFn()
})
onUpdated(updateLabelWidthFn)
onBeforeUnmount(() => {
updateLabelWidth('remove')
removeResizeListener(el.value.firstElementChild as ResizableElement, updateLabelWidthFn)
})
function render() {
if (!slots) return null
if (props.isAutoWidth) {
const autoLabelWidth = elForm.autoLabelWidth
const style = {} as CSSStyleDeclaration
if (autoLabelWidth && autoLabelWidth !== 'auto') {
const marginLeft = parseInt(autoLabelWidth, 10) - computedWidth.value
if (marginLeft) {
style.marginLeft = marginLeft + 'px'
}
}
return h(
'div',
{
ref: el,
class: ['el-form-item__label-wrap'],
style,
},
slots.default?.(),
)
} else {
return h(Fragment, { ref: el }, slots.default?.())
}
}
return render
},
})