自定义组件怎么能像input一样嵌入form表单中, 使用其校验功能(ant vue)
使用 ant vue UI框架时, form表单时常用的组件之一.
内部可以嵌入如 input, select 等子组件, 可以配置字段校验.
但是, 有时, 已有一些组件无法满足需求, 就需要自定义组件作为 form-item.
可是自定义组件怎么还可以用 form 的校验和提示功能呢?
==== 更新 & 解答 2020年3月24日 ====
经过测试发现, 不用任何特殊处理, 自定义组件可直接嵌入 <a-from-item>
中享受form表单的校验功能.
注意:
props.value
+$emit('change')
事件结合(重要).- value 不可设置默认值, 否则报警告:
xxx default value
can not collect, please useoption.initialValue
to set default value.`
测试代码InputX
, a-input
的包装.
- '编辑'和'预览'两种模式切换;
- 预览时内容可控制长度, 超过部分自动隐藏(依赖自定义组件
Ellipsis
).
先看效果图:
演示代码:
<a-form @submit.prevent="searchQuery" :form="form">
<a-form-item label="Tag">
<a-input placeholder="请输入tag名称" v-decorator="[ 'tag', {rules: [{ required: true, message: '请输入tag名称'}]}]"></a-input>
</a-form-item>
<a-form-item label="创建人">
<a-input placeholder="请输入创建人名称" v-decorator="[ 'createBy']"></a-input>
</a-form-item>
<a-form-item>
<InputX placeholder="inputx" v-decorator="[ 'inputx', {rules: [{ required: true, message: '请输入inputx'}]}]"></InputX>
</a-form-item>
</a-form>
<div class="drawer-bootom-button">
<a-button @click="handleSubmit" type="primary">提交</a-button>
</div>
InputX 代码:
<!-- 点击可编辑 -- dafei 2020/1/20 17:38 -->
<template>
<div>
<div class="inputx-item">
<span class="inputx-label" v-if="label">{{label}}</span>
<div>
<div :style="`display: inline-block; width:100%`" @click="handleClick" v-show="viewMode">
<Ellipsis :length="length" :style="`display: inline-block`">{{valueX}}</Ellipsis>
<a-icon v-if="editIcon && !valueX" style="margin-left: 8px;" type="edit" @click="handleClick"/>
</div>
<div v-show="!viewMode">
<a-input ref="editor" v-model="valueX" @blur="handleBlur"
:class="validateMsg?'validate-fail':''"
@change="handleChange" @keyup="handleKeyUp($event)"
@keyup.enter="handleEnter"></a-input>
</div>
<span v-if="validateMsg" class="warn-tip">{{validateMsg}}</span>
</div>
</div>
</div>
</template>
<script>
import Ellipsis from "@comp/Ellipsis/Ellipsis";
export default {
name: "InputX",
components:{Ellipsis},
props:{
defaultValue:{
type:[String,Number],
default: "",
},
value:{
type: [String, Number],
// default: ""
},
// width:{
// type:Number,
// default:120,
// },
length: {
type: Number,
default: 40,
},
editable:{
type:Boolean,
default:false,
},
required:{
type:Boolean,
default:false,
},
/**入参: value; 出参: 校验结果消息, 为null表示校验通过*/
validateRule:{
type:Function,
required:false,
},
label:{
type:String,
required:false,
},
/**独立模式: 点击对否触发编辑; 失去焦点编辑完成*/
alone: {
type:Boolean,
default:true,
},
editIcon:{
type: Boolean,
default: true,
}
},
watch:{
value(n) {
this.valueX = n;
},
editable(n) {
if (n == true) {
this.enableEdit();
} else {
this.disableEdit();
}
}
},
data() {
return {
valueX:this.value || this.defaultValue,
viewMode:!this.editable,
validateMsg: undefined,
}
},
mounted() {
if (this.editable) {
this.validate();
}
},
methods:{
handleClick() {
if (this.alone) {
this.enableEdit();
}
},
handleBlur() {
if (this.alone) {
this.handleOk();
}
},
enableEdit() {
this.viewMode = false;
this.$nextTick(() => { this.$refs.editor.focus()})
this.validate();
},
disableEdit() {
this.viewMode = true;
this.validateMsg = null;
},
handleEnter() {
// 孤立模式下, 才开启回车快捷键
if (this.alone) {
this.handleOk();
}
},
handleOk(e) {
if (!this.validateMsg) {
this.disableEdit();
this.$emit("ok", this.valueX);
}
},
handleChange() {
this.$emit('change', this.valueX);
},
handleKeyUp(e) {
// '' 时, 保持编辑状态
this.validate();
},
validate() {
// 校验
if (this.validateRule != null) {
this.validateMsg = this.validateRule(this.valueX);
}
this.$emit('validate', this.validateMsg ? false : true);
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped>
.warn-tip{
color: #f5222d;
font-size: 14px;
position: absolute;
}
.validate-fail{
border-color: #f5222d;
/*box-shadow:0 0 4px #f5222d;*/
}
.inputx-label{
margin-right: 8px;
}
.inputx-item{
display: flex;
align-items: center;
}
/*.inputx-required{*/
/* display: inline-block;*/
/* margin-right: 4px;*/
/* color: #f5222d;*/
/* font-size: 14px;*/
/* font-family: SimSun, sans-serif;*/
/* line-height: 1;*/
/* content: '*';*/
/*}*/
</style>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
props.value
+$emit('change')
事件结合, 放入<a-form-item>
中自动生效.