UNPKG

element-plus

Version:

A Component Library for Vue 3

1 lines 13.6 kB
{"version":3,"file":"form-item.mjs","sources":["../../../../../../packages/components/form/src/form-item.vue"],"sourcesContent":["<template>\n <div ref=\"formItemRef\" class=\"el-form-item\" :class=\"formItemClass\">\n <LabelWrap\n :is-auto-width=\"labelStyle.width === 'auto'\"\n :update-all=\"elForm.labelWidth === 'auto'\"\n >\n <label\n v-if=\"label || $slots.label\"\n :for=\"labelFor\"\n class=\"el-form-item__label\"\n :style=\"labelStyle\"\n >\n <slot name=\"label\" :label=\"currentLabel\">\n {{ currentLabel }}\n </slot>\n </label>\n </LabelWrap>\n <div class=\"el-form-item__content\" :style=\"contentStyle\">\n <slot></slot>\n <transition name=\"el-zoom-in-top\">\n <slot v-if=\"shouldShowError\" name=\"error\" :error=\"validateMessage\">\n <div\n class=\"el-form-item__error\"\n :class=\"{\n 'el-form-item__error--inline':\n typeof inlineMessage === 'boolean'\n ? inlineMessage\n : elForm.inlineMessage || false,\n }\"\n >\n {{ validateMessage }}\n </div>\n </slot>\n </transition>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport {\n computed,\n defineComponent,\n getCurrentInstance,\n inject,\n onBeforeUnmount,\n onMounted,\n provide,\n reactive,\n ref,\n toRefs,\n watch,\n nextTick,\n} from 'vue'\nimport { NOOP } from '@vue/shared'\nimport AsyncValidator from 'async-validator'\nimport {\n addUnit,\n isValidComponentSize,\n getPropByPath,\n} from '@element-plus/utils'\nimport { elFormItemKey, elFormKey } from '@element-plus/tokens'\nimport { useSize } from '@element-plus/hooks'\nimport LabelWrap from './label-wrap'\n\nimport type { PropType, CSSProperties } from 'vue'\nimport type { ComponentSize } from '@element-plus/constants'\nimport type { ElFormContext, ValidateFieldCallback } from '@element-plus/tokens'\nimport type { FormItemRule } from './form.type'\n\nexport default defineComponent({\n name: 'ElFormItem',\n componentName: 'ElFormItem',\n components: {\n LabelWrap,\n },\n props: {\n label: String,\n labelWidth: {\n type: [String, Number],\n default: '',\n },\n prop: String,\n required: {\n type: Boolean,\n default: undefined,\n },\n rules: [Object, Array] as PropType<FormItemRule | FormItemRule[]>,\n error: String,\n validateStatus: String,\n for: String,\n inlineMessage: {\n type: [String, Boolean],\n default: '',\n },\n showMessage: {\n type: Boolean,\n default: true,\n },\n size: {\n type: String as PropType<ComponentSize>,\n validator: isValidComponentSize,\n },\n },\n setup(props, { slots }) {\n const elForm = inject(elFormKey, {} as ElFormContext)\n const validateState = ref('')\n const validateMessage = ref('')\n const isValidationEnabled = ref(false)\n\n const computedLabelWidth = ref('')\n\n const formItemRef = ref<HTMLDivElement>()\n\n const vm = getCurrentInstance()\n const isNested = computed(() => {\n let parent = vm.parent\n while (parent && parent.type.name !== 'ElForm') {\n if (parent.type.name === 'ElFormItem') {\n return true\n }\n parent = parent.parent\n }\n return false\n })\n\n let initialValue = undefined\n\n watch(\n () => props.error,\n (val) => {\n validateMessage.value = val\n validateState.value = val ? 'error' : ''\n },\n {\n immediate: true,\n }\n )\n watch(\n () => props.validateStatus,\n (val) => {\n validateState.value = val\n }\n )\n\n const labelFor = computed(() => props.for || props.prop)\n const labelStyle = computed(() => {\n const ret: CSSProperties = {}\n if (elForm.labelPosition === 'top') return ret\n const labelWidth = addUnit(props.labelWidth || elForm.labelWidth)\n if (labelWidth) {\n ret.width = labelWidth\n }\n return ret\n })\n const contentStyle = computed(() => {\n const ret: CSSProperties = {}\n if (elForm.labelPosition === 'top' || elForm.inline) {\n return ret\n }\n if (!props.label && !props.labelWidth && isNested.value) {\n return ret\n }\n const labelWidth = addUnit(props.labelWidth || elForm.labelWidth)\n if (!props.label && !slots.label) {\n ret.marginLeft = labelWidth\n }\n return ret\n })\n const fieldValue = computed(() => {\n const model = elForm.model\n if (!model || !props.prop) {\n return\n }\n\n let path = props.prop\n if (path.indexOf(':') !== -1) {\n path = path.replace(/:/, '.')\n }\n\n return getPropByPath(model, path, true).v\n })\n const isRequired = computed(() => {\n const rules = getRules()\n let required = false\n\n if (rules && rules.length) {\n rules.every((rule) => {\n if (rule.required) {\n required = true\n return false\n }\n return true\n })\n }\n return required\n })\n const sizeClass = useSize(undefined, { formItem: false })\n\n const validate = (\n trigger: string,\n callback: ValidateFieldCallback = NOOP\n ) => {\n if (!isValidationEnabled.value) {\n callback()\n return\n }\n const rules = getFilteredRule(trigger)\n if ((!rules || rules.length === 0) && props.required === undefined) {\n callback()\n return\n }\n validateState.value = 'validating'\n const descriptor = {}\n if (rules && rules.length > 0) {\n rules.forEach((rule) => {\n delete rule.trigger\n })\n }\n descriptor[props.prop] = rules\n const validator = new AsyncValidator(descriptor)\n const model = {}\n model[props.prop] = fieldValue.value\n validator.validate(model, { firstFields: true }, (errors, fields) => {\n validateState.value = !errors ? 'success' : 'error'\n validateMessage.value = errors\n ? errors[0].message || `${props.prop} is required`\n : ''\n // fix: #3860 after version 3.5.2, async-validator also return fields if validation fails\n callback(validateMessage.value, errors ? fields : {})\n elForm.emit?.(\n 'validate',\n props.prop,\n !errors,\n validateMessage.value || null\n )\n })\n }\n\n const clearValidate = () => {\n validateState.value = ''\n validateMessage.value = ''\n }\n const resetField = () => {\n const model = elForm.model\n const value = fieldValue.value\n let path = props.prop\n if (path.indexOf(':') !== -1) {\n path = path.replace(/:/, '.')\n }\n const prop = getPropByPath(model, path, true)\n if (Array.isArray(value)) {\n prop.o[prop.k] = [].concat(initialValue)\n } else {\n prop.o[prop.k] = initialValue\n }\n nextTick(() => {\n clearValidate()\n })\n }\n\n const getRules = () => {\n const formRules = elForm.rules\n const selfRules = props.rules\n const requiredRule =\n props.required !== undefined ? { required: !!props.required } : []\n\n const prop = getPropByPath(formRules, props.prop || '', false)\n const normalizedRule = formRules ? prop.o[props.prop || ''] || prop.v : []\n\n return [].concat(selfRules || normalizedRule || []).concat(requiredRule)\n }\n const getFilteredRule = (trigger) => {\n const rules = getRules()\n\n return rules\n .filter((rule) => {\n if (!rule.trigger || trigger === '') return true\n if (Array.isArray(rule.trigger)) {\n return rule.trigger.indexOf(trigger) > -1\n } else {\n return rule.trigger === trigger\n }\n })\n .map((rule) => ({ ...rule }))\n }\n\n const evaluateValidationEnabled = () => {\n isValidationEnabled.value = !!getRules()?.length\n }\n\n const updateComputedLabelWidth = (width: string | number) => {\n computedLabelWidth.value = width ? `${width}px` : ''\n }\n\n const elFormItem = reactive({\n ...toRefs(props),\n size: sizeClass,\n validateState,\n $el: formItemRef,\n evaluateValidationEnabled,\n resetField,\n clearValidate,\n validate,\n updateComputedLabelWidth,\n })\n\n onMounted(() => {\n if (props.prop) {\n elForm?.addField(elFormItem)\n\n const value = fieldValue.value\n initialValue = Array.isArray(value) ? [...value] : value\n\n evaluateValidationEnabled()\n }\n })\n onBeforeUnmount(() => {\n elForm?.removeField(elFormItem)\n })\n\n provide(elFormItemKey, elFormItem)\n\n const formItemClass = computed(() => [\n {\n 'el-form-item--feedback': elForm.statusIcon,\n 'is-error': validateState.value === 'error',\n 'is-validating': validateState.value === 'validating',\n 'is-success': validateState.value === 'success',\n 'is-required': isRequired.value || props.required,\n 'is-no-asterisk': elForm.hideRequiredAsterisk,\n },\n sizeClass.value ? `el-form-item--${sizeClass.value}` : '',\n ])\n\n const shouldShowError = computed(() => {\n return (\n validateState.value === 'error' &&\n props.showMessage &&\n elForm.showMessage\n )\n })\n\n const currentLabel = computed(\n () => (props.label || '') + (elForm.labelSuffix || '')\n )\n\n return {\n formItemRef,\n formItemClass,\n shouldShowError,\n elForm,\n labelStyle,\n contentStyle,\n validateMessage,\n labelFor,\n resetField,\n clearValidate,\n currentLabel,\n }\n },\n})\n</script>\n"],"names":["_withCtx"],"mappings":"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"}