Skip to content

Commit 00bb319

Browse files
AlanLee97nextniko
authored andcommitted
fix(Form): 修复一些bug (DevCloudFE#126)
* fix: 修复updateOn为change时,popover闪一下问题 * fix: 修复提交验证失效问题 * fix: 修改getDfcUID方法名为getFormControlUID
1 parent e3a38d4 commit 00bb319

File tree

2 files changed

+49
-12
lines changed

2 files changed

+49
-12
lines changed

packages/devui-vue/devui/form/src/directive/d-validate-rules.ts

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ interface ValidateFnParam {
1414
messageShowType: MessageShowType
1515
dfcUID: string
1616
popPosition: PopPosition | Array<BasePopPosition>
17+
updateOn?: UpdateOn
1718
}
1819

1920
interface CustomValidatorRuleObject {
@@ -46,6 +47,7 @@ export interface ShowPopoverErrorMessageEventData {
4647
message?: string
4748
uid?: string,
4849
popPosition?: PopPosition
50+
[prop : string]: any
4951
}
5052

5153
type MessageShowType = 'popover' | 'text' | 'none' | 'toast';
@@ -210,17 +212,31 @@ function handleErrorStrategyPass(el: HTMLElement): void {
210212
el.setAttribute('class', classList.join(' '));
211213
}
212214

213-
function handleValidateError({el, tipEl, message, isFormTag, messageShowType, dfcUID, popPosition = 'right-bottom'}: Partial<ValidateFnParam>): void {
215+
function getFormControlUID(el: HTMLElement): string {
216+
if(el.tagName.toLocaleLowerCase() === "body") return "";
217+
let uid = ''
218+
if(el.parentElement.id.startsWith('dfc-')) {
219+
return el.parentElement.id;
220+
}else {
221+
uid = getFormControlUID(el.parentElement);
222+
}
223+
}
224+
225+
function handleValidateError({el, tipEl, message = "", isFormTag, messageShowType, dfcUID, popPosition = 'right-bottom', updateOn}: Partial<ValidateFnParam>): void {
214226
// 如果该指令用在form标签上,这里做特殊处理
215227
if(isFormTag && messageShowType === MessageShowTypeEnum.toast) {
216228
// todo:待替换为toast
217229
alert(message);
218230
return;
219231
}
220232

233+
if(!dfcUID) {
234+
dfcUID = getFormControlUID(el);
235+
}
236+
221237
// messageShowType为popover时,设置popover
222238
if(MessageShowTypeEnum.popover === messageShowType) {
223-
EventBus.emit("showPopoverErrorMessage", {showPopover: true, message, uid: dfcUID, popPosition} as ShowPopoverErrorMessageEventData);
239+
EventBus.emit("showPopoverErrorMessage", {showPopover: true, message, uid: dfcUID, popPosition, updateOn} as ShowPopoverErrorMessageEventData);
224240
return;
225241
}
226242

@@ -250,7 +266,7 @@ function getFormName(binding: DirectiveBinding): string {
250266
}
251267

252268
// 校验处理函数
253-
function validateFn({validator, modelValue, el, tipEl, isFormTag, messageShowType, dfcUID, popPosition}: Partial<ValidateFnParam>) {
269+
function validateFn({validator, modelValue, el, tipEl, isFormTag, messageShowType, dfcUID, popPosition, updateOn}: Partial<ValidateFnParam>) {
254270
validator.validate({modelName: modelValue}).then(() => {
255271
handleValidatePass(el, tipEl);
256272
}).catch((err) => {
@@ -265,7 +281,7 @@ function validateFn({validator, modelValue, el, tipEl, isFormTag, messageShowTyp
265281
msg = errors[0].message;
266282
}
267283

268-
handleValidateError({el, tipEl, message: msg, isFormTag, messageShowType, dfcUID, popPosition});
284+
handleValidateError({el, tipEl, message: msg, isFormTag, messageShowType, dfcUID, popPosition, updateOn});
269285
})
270286
}
271287

@@ -394,14 +410,21 @@ export default {
394410
const htmlEventValidateHandler = (e) => {
395411
const modelValue = e.target.value;
396412
if(messageShowType === MessageShowTypeEnum.popover) {
397-
EventBus.emit("showPopoverErrorMessage", {showPopover: false, message: "", uid: dfcUID, popPosition} as ShowPopoverErrorMessageEventData);
413+
EventBus.emit("showPopoverErrorMessage", {showPopover: false, message: "", uid: dfcUID, popPosition, updateOn} as ShowPopoverErrorMessageEventData);
398414
}
399-
validateFn({validator, modelValue, el, tipEl, isFormTag: false, messageShowType, dfcUID, popPosition});
415+
validateFn({validator, modelValue, el, tipEl, isFormTag: false, messageShowType, dfcUID, popPosition, updateOn});
400416
}
401417

402418
// 监听事件验证
403419
vnode.children[0].el.addEventListener(updateOn, htmlEventValidateHandler);
404420

421+
// 如果校验时机为change,则在focus时关闭popover
422+
if(messageShowType === MessageShowTypeEnum.popover && updateOn === UpdateOnEnum.change) {
423+
vnode.children[0].el.addEventListener('focus', () => {
424+
EventBus.emit("showPopoverErrorMessage", {showPopover: false, uid: dfcUID, updateOn} as ShowPopoverErrorMessageEventData);
425+
});
426+
}
427+
405428
// 设置errorStrategy
406429
if(errorStrategy === ErrorStrategyEnum.pristine) {
407430
handleErrorStrategy(el);
@@ -415,7 +438,7 @@ export default {
415438
const modelValue = isFormTag ? '' : vnode.children[0].el.value;
416439

417440
// 进行提交验证
418-
validateFn({validator, modelValue, el, tipEl, isFormTag, messageShowType});
441+
validateFn({validator, modelValue, el, tipEl, isFormTag, messageShowType, updateOn: 'submit'});
419442
});
420443

421444
}

packages/devui-vue/devui/form/src/form-control/form-control.tsx

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { defineComponent, inject, ref, computed, reactive, onMounted, Teleport }
22
import { uniqueId } from 'lodash-es';
33
import { IForm, formControlProps, formInjectionKey } from '../form-types';
44
import { ShowPopoverErrorMessageEventData } from '../directive/d-validate-rules'
5+
import clickoutsideDirective from '../../../shared/devui-directive/clickoutside'
56
import { EventBus, getElOffset } from '../util';
67
import Icon from '../../../icon/src/icon';
78
import Popover from '../../../popover/src/popover';
@@ -11,6 +12,9 @@ type positionType = 'top' | 'right' | 'bottom' | 'left';
1112

1213
export default defineComponent({
1314
name: 'DFormControl',
15+
directives: {
16+
clickoutside: clickoutsideDirective
17+
},
1418
props: formControlProps,
1519
setup(props, ctx) {
1620
const formControl = ref();
@@ -19,6 +23,7 @@ export default defineComponent({
1923
const isHorizontal = labelData.layout === 'horizontal';
2024
const uid = uniqueId("dfc-");
2125
const showPopover = ref(false);
26+
const updateOn = ref('change');
2227
const tipMessage = ref("");
2328
const popPosition = ref<positionType>("bottom");
2429
let rectInfo: Partial<DOMRect> = {
@@ -38,11 +43,12 @@ export default defineComponent({
3843
EventBus.on("showPopoverErrorMessage", (data: ShowPopoverErrorMessageEventData) => {
3944
if (uid === data.uid) {
4045
rectInfo = el.getBoundingClientRect();
41-
popoverLeftPosition = popPosition.value === "top" || popPosition.value === "bottom" ? rectInfo.right - (rectInfo.width / 2) : rectInfo.right;
42-
popoverTopPosition = popPosition.value === "top" ? elOffset.top + (rectInfo.height / 2) - rectInfo.height : elOffset.top + (rectInfo.height / 2);
4346
showPopover.value = data.showPopover;
4447
tipMessage.value = data.message;
4548
popPosition.value = data.popPosition as any; // todo: 待popover组件positionType完善类型之后再替换类型
49+
popoverLeftPosition = popPosition.value === "top" || popPosition.value === "bottom" ? rectInfo.right - (rectInfo.width / 2) : rectInfo.right;
50+
popoverTopPosition = popPosition.value === "top" ? elOffset.top + (rectInfo.height / 2) - rectInfo.height : elOffset.top + (rectInfo.height / 2);
51+
updateOn.value = data.updateOn ?? 'change';
4652
}
4753
});
4854
});
@@ -60,23 +66,31 @@ export default defineComponent({
6066
}
6167
})
6268

69+
const handleClickOutside = () => {
70+
if(updateOn.value !== 'change') {
71+
showPopover.value = false;
72+
}
73+
}
74+
6375
return () => {
6476
const {
6577
feedbackStatus,
6678
extraInfo,
6779
} = props;
68-
return <div class="form-control" ref={formControl} data-uid={uid}>
69-
<Teleport to="body">
80+
return <div class="form-control" ref={formControl} data-uid={uid} v-clickoutside={handleClickOutside}>
81+
{ showPopover.value &&
82+
<Teleport to="body">
7083
<div style={{
7184
position: 'absolute',
7285
left: popoverLeftPosition + 'px',
7386
top: popoverTopPosition + 'px',
7487
width: rectInfo.width + 'px',
7588
height: rectInfo.height + 'px',
7689
}}>
77-
<Popover visible={showPopover.value} content={tipMessage.value} popType={"error"} position={popPosition.value} />
90+
<Popover controlled={updateOn.value !== 'change'} visible={showPopover.value} content={tipMessage.value} popType={"error"} position={popPosition.value} />
7891
</div>
7992
</Teleport>
93+
}
8094
<div class={`devui-form-control-container${isHorizontal ? ' devui-form-control-container-horizontal' : ''}${feedbackStatus ? ' has-feedback' : ''}${feedbackStatus === 'error' ? ' feedback-error' : ''}`}>
8195
<div class="devui-control-content-wrapper" id={uid}>
8296
{ctx.slots.default?.()}

0 commit comments

Comments
 (0)