feat: Input 组件新增clear-triger属性 (#476)

 Closes: #462
This commit is contained in:
不如摸鱼去 2024-07-31 23:06:00 +08:00 committed by GitHub
parent bb3d3292af
commit 364cfbf1af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 106 additions and 51 deletions

View File

@ -44,6 +44,21 @@ function handleChange(event) {
<wd-input v-model="value" clearable @change="handleChange"/>
```
## 有值且聚焦时展示清空按钮
设置 `clear-trigger` 属性,可以控制是否聚焦时才展示清空按钮。
```html
<wd-input v-model="value" clear-trigger="focus" clearable @change="handleChange"/>
```
## 点击清除按钮时不自动聚焦
设置`focus-when-clear` 属性,可以控制点击清除按钮时是否自动聚焦。
```html
<wd-input type="text" :focus-when-clear="false" v-model="value" clearable />
```
## 密码输入框
设置 `show-password` 属性。
@ -150,6 +165,9 @@ function handleChange(event) {
| no-border | 非 cell 类型下是否隐藏下划线 | boolean | - | false | - | - |
| prop | 表单域 `model` 字段名,在使用表单校验功能的情况下,该属性是必填的 | string | - | - | - |
| rules | 表单验证规则,结合`wd-form`组件使用 | `FormItemRule []` | - | `[]` | - |
| clearTrigger | 显示清除图标的时机always 表示输入框不为空时展示focus 表示输入框聚焦且不为空时展示 | `InputClearTrigger` | `focus` / `always` | `always` | $LOWEST_VERSION$ |
| focusWhenClear | 是否在点击清除按钮时聚焦输入框 | boolean | - | true | $LOWEST_VERSION$ |
### FormItemRule 数据结构

View File

@ -141,18 +141,6 @@ function changeSearchType({ item, index }) {
<wd-search placeholder="请输入订单号/订单名称" cancel-txt="搜索" />
```
<!-- 通过设置 `use-action-slot` 来自定义输入框左边内容,设置`use-action-slot` 使用自定义内容替换取消按钮。
```html
<wd-search use-label-slot use-action-slot>
<template #label>
<view style="line-height: 14px;margin-right: 10px;">左侧</view>
</template>
<template #action>
<view style="padding: 5px 10px;color: #ff0000;">右侧</view>
</template>
</wd-search>
``` -->
## Attributes

View File

@ -15,6 +15,12 @@
<demo-block title="清空按钮">
<wd-input type="text" @input="handleInput" v-model="value4" clearable @change="handleChange1" />
</demo-block>
<demo-block title="有值且聚焦时展示清空按钮">
<wd-input type="text" clear-trigger="focus" @input="handleInput" v-model="value20" clearable @change="handleChange1" />
</demo-block>
<demo-block title="点击清除按钮时不自动聚焦">
<wd-input type="text" :focus-when-clear="false" @input="handleInput" v-model="value21" clearable @change="handleChange1" />
</demo-block>
<demo-block title="密码框">
<wd-input type="text" @input="handleInput" v-model="value5" clearable show-password @change="handleChange2" />
</demo-block>
@ -45,7 +51,7 @@
<wd-input type="text" label="错误状态" v-model="value15" @input="handleInput" placeholder="请输入用户名" error />
<wd-input type="text" label="必填" v-model="value16" @input="handleInput" placeholder="请输入用户名" required />
<wd-input type="text" label="图标" v-model="value17" @input="handleInput" placeholder="请输入..." prefix-icon="dong" suffix-icon="list" />
<wd-input type="text" label="自定义插槽" center v-model="value18" @input="handleInput" placeholder="请输入..." use-suffix-slot clearable>
<wd-input type="text" label="自定义插槽" center v-model="value18" @input="handleInput" placeholder="请输入..." clearable>
<template #suffix>
<wd-button size="small" custom-class="button">获取验证码</wd-button>
</template>
@ -76,6 +82,8 @@ const value16 = ref<string>('')
const value17 = ref<string>('')
const value18 = ref<string>('')
const value19 = ref<string>('')
const value20 = ref<string>('')
const value21 = ref<string>('')
function handleChange(event: any) {
console.log(event)

View File

@ -1,6 +1,8 @@
import { baseProps, makeArrayProp, makeBooleanProp, makeNumberProp, makeNumericProp, makeStringProp } from '../common/props'
import type { FormItemRule } from '../wd-form/types'
export type InputClearTrigger = 'focus' | 'always'
export const inputProps = {
...baseProps,
customInputClass: makeStringProp(''),
@ -155,5 +157,16 @@ export const inputProps = {
/**
* wd-form组件使用
*/
rules: makeArrayProp<FormItemRule>()
rules: makeArrayProp<FormItemRule>(),
/**
* always focus
*/
clearTrigger: makeStringProp<InputClearTrigger>('always'),
/**
*
* 类型: boolean
* 默认值: true
* 最低版本: $LOWEST_VERSION$
*/
focusWhenClear: makeBooleanProp(true)
}

View File

@ -30,7 +30,7 @@
:placeholder="placeholder || translate('placeholder')"
:disabled="disabled"
:maxlength="maxlength"
:focus="isFocus"
:focus="focused"
:confirm-type="confirmType"
:confirm-hold="confirmHold"
:cursor="cursor"
@ -49,7 +49,7 @@
@keyboardheightchange="handleKeyboardheightchange"
/>
<view v-if="readonly" class="wd-input__readonly-mask" />
<view v-if="showClear || showPassword || suffixIcon || showWordCount || useSuffixSlot" class="wd-input__suffix">
<view v-if="showClear || showPassword || suffixIcon || showWordCount || $slots.suffix" class="wd-input__suffix">
<wd-icon v-if="showClear" custom-class="wd-input__clear" name="error-fill" @click="clear" />
<wd-icon v-if="showPassword" custom-class="wd-input__icon" :name="isPwdVisible ? 'view' : 'eye-close'" @click="togglePwdVisible" />
<view v-if="showWordCount" class="wd-input__count">
@ -85,7 +85,7 @@ export default {
<script lang="ts" setup>
import { computed, onBeforeMount, ref, watch } from 'vue'
import { objToStyle, requestAnimationFrame } from '../common/util'
import { isDef, objToStyle, requestAnimationFrame } from '../common/util'
import { useCell } from '../composables/useCell'
import { FORM_KEY, type FormItemRule } from '../wd-form/types'
import { useParent } from '../composables/useParent'
@ -102,25 +102,23 @@ const emit = defineEmits([
'input',
'keyboardheightchange',
'confirm',
'linechange',
'clicksuffixicon',
'clickprefixicon',
'click'
])
const { translate } = useTranslate('input')
const showClear = ref<boolean>(false)
const showWordCount = ref<boolean>(false)
const isPwdVisible = ref<boolean>(false)
const clearing = ref<boolean>(false)
const isFocus = ref<boolean>(false) //
const clearing = ref<boolean>(false) //
const focused = ref<boolean>(false) //
const focusing = ref<boolean>(false) //
const inputValue = ref<string | number>('') //
const cell = useCell()
watch(
() => props.focus,
(newValue) => {
isFocus.value = newValue
focused.value = newValue
},
{ immediate: true, deep: true }
)
@ -128,19 +126,40 @@ watch(
watch(
() => props.modelValue,
(newValue) => {
const { disabled, readonly, clearable } = props
if (newValue === undefined) {
newValue = ''
console.warn('[wot-design] warning(wd-input): value can not be undefined.')
}
inputValue.value = newValue
showClear.value = Boolean(clearable && !disabled && !readonly && newValue)
},
{ immediate: true, deep: true }
)
const { parent: form } = useParent(FORM_KEY)
/**
* 展示清空按钮
*/
const showClear = computed(() => {
const { disabled, readonly, clearable, clearTrigger } = props
if (clearable && !readonly && !disabled && inputValue.value && (clearTrigger === 'always' || (props.clearTrigger === 'focus' && focusing.value))) {
return true
} else {
return false
}
})
/**
* 展示字数统计
*/
const showWordCount = computed(() => {
const { disabled, readonly, maxlength, showWordLimit } = props
return Boolean(!disabled && !readonly && isDef(maxlength) && maxlength > -1 && showWordLimit)
})
/**
* 表单错误提示信息
*/
const errorMessage = computed(() => {
if (form && props.prop && form.errorMessages && form.errorMessages[props.prop]) {
return form.errorMessages[props.prop]
@ -194,41 +213,50 @@ onBeforeMount(() => {
//
function initState() {
const { disabled, readonly, clearable, maxlength, showWordLimit } = props
let newVal = ''
if (showWordLimit && maxlength && inputValue.value.toString().length > maxlength) {
newVal = inputValue.value.toString().substring(0, maxlength)
}
showClear.value = Boolean(!disabled && !readonly && clearable && inputValue.value)
showWordCount.value = Boolean(!disabled && !readonly && maxlength && showWordLimit)
inputValue.value = newVal || inputValue.value
inputValue.value = formatValue(inputValue.value)
emit('update:modelValue', inputValue.value)
}
function formatValue(value: string | number) {
const { maxlength } = props
if (isDef(maxlength) && maxlength !== -1 && String(value).length > maxlength) {
return value.toString().slice(0, maxlength)
}
return value
}
function togglePwdVisible() {
isPwdVisible.value = !isPwdVisible.value
}
function clear() {
clearing.value = true
focusing.value = false
inputValue.value = ''
requestAnimationFrame()
.then(() => requestAnimationFrame())
.then(() => requestAnimationFrame())
.then(() => {
isFocus.value = true
emit('change', {
value: ''
})
emit('update:modelValue', inputValue.value)
emit('clear')
if (props.focusWhenClear) {
focused.value = false
}
requestAnimationFrame(() => {
if (props.focusWhenClear) {
focused.value = true
focusing.value = true
}
emit('change', {
value: ''
})
emit('update:modelValue', inputValue.value)
emit('clear')
})
}
function handleBlur() {
isFocus.value = false
emit('change', {
value: inputValue.value
})
emit('update:modelValue', inputValue.value)
emit('blur', {
value: inputValue.value
if (clearing.value) {
clearing.value = false
return
}
requestAnimationFrame(() => {
focusing.value = false
emit('blur', {
value: inputValue.value
})
})
}
function handleFocus({ detail }: any) {
@ -236,7 +264,7 @@ function handleFocus({ detail }: any) {
clearing.value = false
return
}
isFocus.value = true
focusing.value = true
emit('focus', detail)
}
function handleInput({ detail }: any) {