feat(Field): add formatter prop (#5534)

This commit is contained in:
neverland 2020-01-09 20:52:20 +08:00 committed by GitHub
parent 47c24e192c
commit 9452444a7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 200 additions and 94 deletions

View File

@ -126,17 +126,43 @@ Use `error` or `error-message` to show error info
Use button slot to insert button Use button slot to insert button
```html ```html
<van-cell-group> <van-field
<van-field
v-model="sms" v-model="sms"
center center
clearable clearable
label="SMS" label="SMS"
placeholder="SMS" placeholder="SMS"
> >
<van-button slot="button" size="small" type="primary">Send SMS</van-button> <van-button slot="button" size="small" type="primary">Send SMS</van-button>
</van-field> </van-field>
</van-cell-group> ```
### Format Value
Use `formatter` prop to format the input value
```html
<van-field
v-model="value"
label="Text"
:formatter="formatter"
placeholder="Format Value"
/>
```
```js
export default {
data() {
return {
value: ''
};
},
methods: {
formatter(value) {
return value.replace(/\d/g, '');
}
}
}
``` ```
### Auto Resize ### Auto Resize
@ -144,33 +170,29 @@ Use button slot to insert button
Textarea Field can be auto resize when has `autosize` prop Textarea Field can be auto resize when has `autosize` prop
```html ```html
<van-cell-group> <van-field
<van-field
v-model="message" v-model="message"
label="Message" label="Message"
type="textarea" type="textarea"
placeholder="Message" placeholder="Message"
rows="1" rows="1"
autosize autosize
/> />
</van-cell-group>
``` ```
### Show Word Limit ### Show Word Limit
```html ```html
<van-cell-group> <van-field
<van-field
v-model="message" v-model="message"
rows="2" rows="2"
autosize autosize
label="留言" label="Message"
type="textarea" type="textarea"
maxlength="50" maxlength="50"
placeholder="请输入留言" placeholder="Message"
show-word-limit show-word-limit
/> />
</van-cell-group>
``` ```
## API ## API
@ -195,6 +217,7 @@ Textarea Field can be auto resize when has `autosize` prop
| autofocus | Whether to auto focus, unsupported in iOS | *boolean* | `false` | - | | autofocus | Whether to auto focus, unsupported in iOS | *boolean* | `false` | - |
| show-word-limit | Whether to show word limit, need to set the `maxlength` prop | *boolean* | `false` | 2.2.8 | | show-word-limit | Whether to show word limit, need to set the `maxlength` prop | *boolean* | `false` | 2.2.8 |
| error | Whether to show error info | *boolean* | `false` | - | | error | Whether to show error info | *boolean* | `false` | - |
| formatter | Input value formatter | *Function* | - | 2.4.2 |
| arrow-direction | Can be set to `left` `up` `down` | *string* | - | 2.0.4 | | arrow-direction | Can be set to `left` `up` `down` | *string* | - | 2.0.4 |
| error-message | Error message | *string* | `''` | - | | error-message | Error message | *string* | `''` | - |
| label-class | Label className | *any* | - | - | | label-class | Label className | *any* | - | - |

View File

@ -142,17 +142,44 @@ export default {
通过 button 插槽可以在输入框尾部插入按钮 通过 button 插槽可以在输入框尾部插入按钮
```html ```html
<van-cell-group> <van-field
<van-field
v-model="sms" v-model="sms"
center center
clearable clearable
label="短信验证码" label="短信验证码"
placeholder="请输入短信验证码" placeholder="请输入短信验证码"
> >
<van-button slot="button" size="small" type="primary">发送验证码</van-button> <van-button slot="button" size="small" type="primary">发送验证码</van-button>
</van-field> </van-field>
</van-cell-group> ```
### 格式化输入内容
通过`formatter`属性可以对输入的内容进行格式化
```html
<van-field
v-model="value"
label="文本"
:formatter="formatter"
placeholder="格式化输入内容"
/>
```
```js
export default {
data() {
return {
value: ''
};
},
methods: {
formatter(value) {
// 过滤输入的数字
return value.replace(/\d/g, '');
}
}
}
``` ```
### 高度自适应 ### 高度自适应
@ -160,16 +187,14 @@ export default {
对于 textarea可以通过`autosize`属性设置高度自适应 对于 textarea可以通过`autosize`属性设置高度自适应
```html ```html
<van-cell-group> <van-field
<van-field
v-model="message" v-model="message"
rows="1" rows="1"
autosize autosize
label="留言" label="留言"
type="textarea" type="textarea"
placeholder="请输入留言" placeholder="请输入留言"
/> />
</van-cell-group>
``` ```
### 显示字数统计 ### 显示字数统计
@ -177,8 +202,7 @@ export default {
设置`maxlength``show-word-limit`属性后会在底部显示字数统计 设置`maxlength``show-word-limit`属性后会在底部显示字数统计
```html ```html
<van-cell-group> <van-field
<van-field
v-model="message" v-model="message"
rows="2" rows="2"
autosize autosize
@ -187,8 +211,7 @@ export default {
maxlength="50" maxlength="50"
placeholder="请输入留言" placeholder="请输入留言"
show-word-limit show-word-limit
/> />
</van-cell-group>
``` ```
## API ## API
@ -213,6 +236,7 @@ export default {
| autofocus | 是否自动聚焦iOS 系统不支持该属性 | *boolean* | `false` | - | | autofocus | 是否自动聚焦iOS 系统不支持该属性 | *boolean* | `false` | - |
| show-word-limit | 是否显示字数统计,需要设置`maxlength`属性 | *boolean* | `false` | 2.2.8 | | show-word-limit | 是否显示字数统计,需要设置`maxlength`属性 | *boolean* | `false` | 2.2.8 |
| error | 是否将输入内容标红 | *boolean* | `false` | - | | error | 是否将输入内容标红 | *boolean* | `false` | - |
| formatter | 输入内容格式化函数 | *Function* | - | 2.4.2 |
| arrow-direction | 箭头方向,可选值为 `left` `up` `down` | *string* | - | 2.0.4 | | arrow-direction | 箭头方向,可选值为 `left` `up` `down` | *string* | - | 2.0.4 |
| error-message | 底部错误提示文案,为空时不展示 | *string* | `''` | - | error-message | 底部错误提示文案,为空时不展示 | *string* | `''` | -
| label-class | 左侧文本额外类名 | *any* | - | - | | label-class | 左侧文本额外类名 | *any* | - | - |
@ -220,7 +244,7 @@ export default {
| label-align | 左侧文本对齐方式,可选值为 `center` `right` | *string* | `left` | - | | label-align | 左侧文本对齐方式,可选值为 `center` `right` | *string* | `left` | - |
| input-align | 输入框内容对齐方式,可选值为 `center` `right` | *string* | `left` | - | | input-align | 输入框内容对齐方式,可选值为 `center` `right` | *string* | `left` | - |
| error-message-align | 错误提示文案对齐方式,可选值为 `center` `right` | *string* | `left` | - | | error-message-align | 错误提示文案对齐方式,可选值为 `center` `right` | *string* | `left` | - |
| autosize | 自适应内容高度,只对 textarea 有效,可传入对象,<br>如 { maxHeight: 100, minHeight: 50 },单位为`px` | *boolean \| object* | `false` | - | | autosize | 是否自适应内容高度,只对 textarea 有效,<br>可传入对象,如 { maxHeight: 100, minHeight: 50 }<br>单位为`px` | *boolean \| object* | `false` | - |
| left-icon | 左侧图标名称或图片链接,可选值见 [Icon 组件](#/zh-CN/icon) | *string* | - | - | | left-icon | 左侧图标名称或图片链接,可选值见 [Icon 组件](#/zh-CN/icon) | *string* | - | - |
| right-icon | 右侧图标名称或图片链接,可选值见 [Icon 组件](#/zh-CN/icon) | *string* | - | - | | right-icon | 右侧图标名称或图片链接,可选值见 [Icon 组件](#/zh-CN/icon) | *string* | - | - |

View File

@ -6,7 +6,7 @@
</van-cell-group> </van-cell-group>
</demo-block> </demo-block>
<demo-block :title="$t('title2')"> <demo-block :title="$t('customType')">
<van-cell-group> <van-cell-group>
<van-field <van-field
v-model="text" v-model="text"
@ -44,7 +44,7 @@
</van-cell-group> </van-cell-group>
</demo-block> </demo-block>
<demo-block :title="$t('title3')"> <demo-block :title="$t('disabled')">
<van-cell-group> <van-cell-group>
<van-field :value="$t('inputReadonly')" :label="$t('text')" readonly /> <van-field :value="$t('inputReadonly')" :label="$t('text')" readonly />
<van-field :value="$t('inputDisabled')" :label="$t('text')" disabled /> <van-field :value="$t('inputDisabled')" :label="$t('text')" disabled />
@ -70,7 +70,7 @@
</van-cell-group> </van-cell-group>
</demo-block> </demo-block>
<demo-block :title="$t('title4')"> <demo-block :title="$t('errorInfo')">
<van-cell-group> <van-cell-group>
<van-field <van-field
v-model="username" v-model="username"
@ -89,7 +89,7 @@
</van-cell-group> </van-cell-group>
</demo-block> </demo-block>
<demo-block :title="$t('title6')"> <demo-block :title="$t('insertButton')">
<van-cell-group> <van-cell-group>
<van-field <van-field
center center
@ -107,6 +107,17 @@
</van-cell-group> </van-cell-group>
</demo-block> </demo-block>
<demo-block v-if="!isWeapp" :title="$t('formatValue')">
<van-cell-group>
<van-field
v-model="formatValue"
:label="$t('text')"
:formatter="formatter"
:placeholder="$t('formatValue')"
/>
</van-cell-group>
</demo-block>
<demo-block :title="$t('textareaAutosize')"> <demo-block :title="$t('textareaAutosize')">
<van-cell-group> <van-cell-group>
<van-field <van-field
@ -141,58 +152,60 @@
export default { export default {
i18n: { i18n: {
'zh-CN': { 'zh-CN': {
title2: '自定义类型',
title3: '禁用输入框',
title4: '错误提示',
title6: '插入按钮',
sms: '短信验证码',
tel: '手机号', tel: '手机号',
sms: '短信验证码',
text: '文本', text: '文本',
digit: '整数', digit: '整数',
phone: '手机号', phone: '手机号',
number: '数字', number: '数字',
message: '留言', message: '留言',
sendSMS: '发送验证码', sendSMS: '发送验证码',
disabled: '禁用输入框',
showIcon: '显示图标', showIcon: '显示图标',
errorInfo: '错误提示',
customType: '自定义类型',
phoneError: '手机号格式错误',
formatValue: '格式化输入内容',
insertButton: '插入按钮',
showClearIcon: '显示清除图标', showClearIcon: '显示清除图标',
showWordLimit: '显示字数统计', showWordLimit: '显示字数统计',
textareaAutosize: '高度自适应', inputReadonly: '输入框只读',
inputDisabled: '输入框已禁用',
smsPlaceholder: '请输入短信验证码', smsPlaceholder: '请输入短信验证码',
textPlaceholder: '请输入文本', textPlaceholder: '请输入文本',
digitPlaceholder: '请输入整数', digitPlaceholder: '请输入整数',
numberPlaceholder: '请输入数字(支持小数)',
phonePlaceholder: '请输入手机号', phonePlaceholder: '请输入手机号',
messagePlaceholder: '请输入留言', textareaAutosize: '高度自适应',
inputReadonly: '输入框只读', numberPlaceholder: '请输入数字(支持小数)',
inputDisabled: '输入框已禁用', messagePlaceholder: '请输入留言'
phoneError: '手机号格式错误'
}, },
'en-US': { 'en-US': {
title2: 'Custom Type',
title3: 'Disabled',
title4: 'Error Info',
title6: 'Insert Button',
sms: 'SMS',
tel: 'Tel', tel: 'Tel',
sms: 'SMS',
text: 'Text', text: 'Text',
digit: 'Digit', digit: 'Digit',
phone: 'Phone', phone: 'Phone',
number: 'Number', number: 'Number',
message: 'Message', message: 'Message',
sendSMS: 'Send SMS', sendSMS: 'Send SMS',
disabled: 'Disabled',
showIcon: 'Show Icon', showIcon: 'Show Icon',
errorInfo: 'Error Info',
customType: 'Custom Type',
phoneError: 'Invalid phone',
formatValue: 'Format Value',
insertButton: 'Insert Button',
showClearIcon: 'Show Clear Icon', showClearIcon: 'Show Clear Icon',
showWordLimit: 'Show Word Limit', showWordLimit: 'Show Word Limit',
textareaAutosize: 'Auto Resize', inputReadonly: 'Input Readonly',
inputDisabled: 'Input Disabled',
smsPlaceholder: 'SMS', smsPlaceholder: 'SMS',
textPlaceholder: 'Text', textPlaceholder: 'Text',
digitPlaceholder: 'Digit', digitPlaceholder: 'Digit',
phonePlaceholder: 'Phone', phonePlaceholder: 'Phone',
textareaAutosize: 'Auto Resize',
numberPlaceholder: 'Number', numberPlaceholder: 'Number',
messagePlaceholder: 'Message', messagePlaceholder: 'Message'
inputReadonly: 'Input Readonly',
inputDisabled: 'Input Disabled',
phoneError: 'Invalid phone'
} }
}, },
@ -211,8 +224,15 @@ export default {
message: '', message: '',
message2: '', message2: '',
phone: '', phone: '',
phone2: '12345' phone2: '12345',
formatValue: ''
}; };
},
methods: {
formatter(value) {
return value.replace(/\d/g, '');
}
} }
}; };
</script> </script>

View File

@ -20,6 +20,7 @@ export default createComponent({
leftIcon: String, leftIcon: String,
rightIcon: String, rightIcon: String,
clearable: Boolean, clearable: Boolean,
formatter: Function,
maxlength: [Number, String], maxlength: [Number, String],
labelWidth: [Number, String], labelWidth: [Number, String],
labelClass: null, labelClass: null,
@ -99,7 +100,6 @@ export default createComponent({
} }
}, },
// native maxlength not work when type = number
format(target = this.$refs.input) { format(target = this.$refs.input) {
if (!target) { if (!target) {
return; return;
@ -108,6 +108,7 @@ export default createComponent({
let { value } = target; let { value } = target;
const { maxlength } = this; const { maxlength } = this;
// native maxlength not work when type is number
if (isDef(maxlength) && value.length > maxlength) { if (isDef(maxlength) && value.length > maxlength) {
value = value.slice(0, maxlength); value = value.slice(0, maxlength);
target.value = value; target.value = value;
@ -124,6 +125,16 @@ export default createComponent({
} }
} }
if (this.formatter) {
const originValue = value;
value = this.formatter(value);
if (value !== originValue) {
target.value = value;
}
}
return value; return value;
}, },

View File

@ -115,6 +115,16 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
</div> </div>
<div>
<div class="van-cell-group van-hairline--top-bottom">
<div class="van-cell van-field">
<div class="van-cell__title van-field__label"><span>文本</span></div>
<div class="van-cell__value">
<div class="van-field__body"><input type="text" placeholder="格式化输入内容" class="van-field__control"></div>
</div>
</div>
</div>
</div>
<div> <div>
<div class="van-cell-group van-hairline--top-bottom"> <div class="van-cell-group van-hairline--top-bottom">
<div class="van-cell van-field"> <div class="van-cell van-field">

View File

@ -262,3 +262,21 @@ test('arrow-direction prop', () => {
}); });
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('formatter prop', () => {
const wrapper = mount(Field, {
propsData: {
value: 'abc123',
formatter: (value) => value.replace(/\d/g, '')
}
});
const input = wrapper.find('input');
input.trigger('input');
expect(wrapper.emitted('input')[0][0]).toEqual('abc');
input.element.value = '123efg';
input.trigger('input');
expect(wrapper.emitted('input')[1][0]).toEqual('efg');
});