element-ui form custom validator refs duplicate bug All In One
element-ui form custom validator refs duplicate bug All In One
自定义校验规则,通过 refs 调用子组件的 showError 方法;出现多个 tab 下的表单,使用当前激活的组件验证规则;
<template>
<section class="creative-text2-container">
<el-input
:placeholder="placeholder"
class="creative-text-input"
:disabled="isLock"
v-model="title"
@input="autoTrimTitle"
@blur="titleLibChange">
</el-input>
<el-button
class="creative-text-btn"
plain
:disabled="isLock"
@click="openTitleLibModal">
文案库
</el-button>
<el-popover
:disabled="isLock"
placement="top"
trigger="click"
popper-class="ks-popover">
<div
class="word p-t-5 p-b-5 hand"
v-for="word in customWords"
:key="word.id"
@click="handleAddIntoTitle(word)">
{{word.name}}
</div>
<el-button
slot="reference"
class="creative-words-btn"
plain
:disabled="isLock">
动态词包
</el-button>
</el-popover>
<div
class="creative-text-title"
:class="isLock && 'lock-title' ">
<span :class="isMaxError && 'max-limit-error'">{{getTitleBytesLength(title)}}</span>/<span>{{maxTitleLength}}</span>
</div>
</section>
</template>
<script>
import Util from '@/utils';
import UtilCache from '@/utils/cache';
export default {
name: 'CreativeTexts',
components: {
//
},
props: {
creativeObj: {
type: Object,
default: () => ({}),
},
titleIndex: {
type: Number,
default: 0,
},
// dict
customWords: {
type: Array,
default: () => [],
},
sensitiveList: {
type: Array,
default: () => [],
},
prohibitedList: {
type: Array,
default: () => [],
},
checkMinLength: {
type: Boolean,
default: false,
},
minTitleLength: {
type: Number,
default: 1,
},
maxTitleLength: {
type: Number,
default: 30,
// default: 14,
},
isLock: {
type: Boolean,
default: false,
},
titleType: {
type: String,
default: 'descList',
},
titleDesc: {
type: String,
default: '创意文案',
},
},
data () {
return {
title: '',
};
},
watch: {
creativeObj: {
handler (obj) {
this.title = obj[this.titleType][this.titleIndex].title;
},
deep: true,
}
},
computed: {
placeholder () {
return `请输入${this.titleDesc}(${this.minTitleLength}-${this.maxTitleLength}字)`;
},
isMaxError () {
return this.getTitleLength > this.maxTitleLength;
},
isMinError () {
return this.getTitleLength < this.minTitleLength;
},
getTitleLength () {
const name = this.creativeObj[this.titleType][this.titleIndex].title || '';
return this.getTitleBytesLength(name.trim());
},
isEmpty () {
return this.getTitleLength === 0;
},
},
mounted () {
this.init();
},
methods: {
init () {
this.title = this.creativeObj[this.titleType][this.titleIndex].title;
},
titleGeneratopr () {
const titleObj = {
title: '',
creative_word_ids: '',
sensitiveList: [],
};
return titleObj;
},
getTitleBytesLength (str = '') {
const customWords = this.customWords;
if(!str) {
return 0;
}
const names = [];
// 获取动态词包
for(const obj of customWords) {
if(str.includes(obj.rel_name)) {
names.push(obj.rel_name);
}
}
// 获取动态词包长度
const getLength = (name = '') => {
return customWords.filter(obj => name === obj.rel_name)[0].max_word_len;
};
let result = 0;
for(const name of names) {
// 处理重复
while(str.includes(name)){
result += parseInt(getLength(name));
str = str.replace(name, '');
}
}
// 剩余字符串,长度 (中文两个字节,英文一个字节)
const bytes = Util.getByteLen(str);
return (result + Math.ceil(bytes / 2));
},
handleAddIntoTitle (obj) {
this.title = this.creativeObj[this.titleType][this.titleIndex].title + obj.rel_name;
this.creativeObj[this.titleType][this.titleIndex].title = this.title;
},
autoTrimTitle () {
this.creativeObj[this.titleType][this.titleIndex].title = this.title.trim();
},
getSensitives (str = '') {
const sensitives = [];
for (const item of this.sensitiveList) {
if(str.includes(item)) {
str = str.replace(item, '');
sensitives.push(item);
}
}
this.creativeObj[this.titleType][this.titleIndex].sensitiveList = sensitives;
},
titleLibChange () {
this.autoTrimTitle();
this.showError();
},
showError () {
this.getSensitives(this.title);
let errorMsg = '';
if(this.isEmpty) {
errorMsg = `请输入${this.titleDesc}`;
} else {
if(this.isMaxError) {
errorMsg = `长度超过${this.maxTitleLength}字`;
}
if(this.checkMinLength && this.isMinError) {
errorMsg = `长度少于${this.minTitleLength}字`;
}
}
return errorMsg;
},
openTitleLibModal () {
this.$emit('open-title-type', this.titleType, this.titleIndex);
},
},
};
</script>
<style lang="scss" scoped>
.creative-text2-container {
box-sizing: border-box;
position: relative;
overflow: hidden;
width: 660px;
min-width: 660px;
.creative-text-input {
box-sizing: border-box;
width: 480px;
}
.creative-text-btn,
.creative-words-btn {
box-sizing: border-box;
width: 80px;
margin-left: 5px;
}
.creative-text-title {
position: absolute;
display: inline-block;
right: 181px;
top: 8px;
width: auto;
text-align: right;
background: #fff;
padding: 1px 9px 1px 5px;
height: 17px;
font-size: 12px;
color: #909399;
line-height: 17px;
.max-limit-error {
color: #f56d6d;
}
}
.lock-title {
box-sizing: border-box;
}
}
</style>
<!-- 多组创意文案-->
<el-form-item
class="gdt-creative-title-question-item"
:class="isRequired && 'is-required'"
label="创意文案">
<el-tooltip
effect="dark"
:content="`使用广告位:${getPositions}`"
placement="right">
<icon-svg class="icon-question-circle" icon-class="question-circle-o"></icon-svg>
</el-tooltip>
<section class="text-add-group-container">
<section
class="text-add-group-boxs"
v-for="(item, index) in textGroupList"
:key="(index)">
<div class="text-add-group-box">
<el-form-item
label=""
:prop="`creativeList.${creativeIndex}.descList.${index}.title`"
:rules="[
{
required: true,
validator: (rule, value, callback) => descListValidator(rule, value, callback, index),
// message: '自定义表单验证方法错误信息',
trigger: 'blur',
},
]">
<CreativeTexts
ref="creativeTextsRef1"
titleType="descList"
:titleIndex="index"
:checkMinLength="false"
:minTitleLength="1"
:maxTitleLength="30"
:creativeObj="creativeObj"
:customWords="customWords"
:sensitiveList="sensitiveList"
:prohibitedList="prohibitedList"
@validate-field="validateFieldByKey"
@open-title-type="openTitleLibraryModal('descList', index)"
/>
</el-form-item>
<div
v-if="textGroupList.length > 1"
class="delete-icon-box">
<div>
<icon-svg
icon-class="delete"
class="delete-icon"
@click="removeDescGroup(index)"
/>
</div>
</div>
</div>
<el-form-item
v-if="isShowDescListSensitives(index)"
class="creative-text-input-warning-box"
label="">
<div class="creative-text-input-warning">
<el-alert
type="warning"
:closable="false"
:title="`包含敏感词:${getDescListSensitives(index)}`">
</el-alert>
</div>
</el-form-item>
</section>
<div
v-if="leftNum > 0"
class="add-group-btn-box"
@click="addDescGroup">
<span class="add-group-btn-text">
<icon-svg icon-class="tianjia1" />
<span>还可以添加{{leftNum}}组</span>
</span>
</div>
</section>
</el-form-item>
titleValidator (rule, value, callback) {
const errMsg = this.$refs.titleRef1.showError();
this.customValidator(errMsg, callback);
},
descListValidator (rule, value, callback, index) {
// 多组文案,需要获取到对应的 index
const errMsg = this.$refs.creativeTextsRef1[index].showError();
this.customValidator(errMsg, callback);
},
helpTextValidator (rule, value, callback) {
const errMsg = this.$refs.helpTextRef.showError();
this.customValidator(errMsg, callback);
},
customValidator (errMsg = '', callback, flag = true) {
if (!errMsg) {
callback();
} else {
if(flag) {
callback(errMsg);
} else {
// 不显示 error 信息
callback(new Error(' '));
}
}
},
validateFieldByKey () {
//
},
refs
©xgqfrms 2012-2020
www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!
原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/15160806.html
未经授权禁止转载,违者必究!