[Improvement] Field: add button slot (#772)

This commit is contained in:
neverland 2018-03-25 22:12:24 +08:00 committed by GitHub
parent 199ec0cd85
commit 45859cf0a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 127 additions and 93 deletions

View File

@ -35,7 +35,12 @@
<demo-block :title="$t('title4')"> <demo-block :title="$t('title4')">
<van-cell-group> <van-cell-group>
<van-field :label="$t('username')" :placeholder="$t('usernamePlaceholder')" error /> <van-field
v-model="username2"
:label="$t('username')"
:placeholder="$t('usernamePlaceholder')"
error
/>
<van-field <van-field
v-model="phone" v-model="phone"
:label="$t('phone')" :label="$t('phone')"
@ -53,10 +58,25 @@
type="textarea" type="textarea"
:placeholder="$t('messagePlaceholder')" :placeholder="$t('messagePlaceholder')"
rows="1" rows="1"
:autosize="{ maxHeight: 100, minHeight: 40 }" autosize
/> />
</van-cell-group> </van-cell-group>
</demo-block> </demo-block>
<demo-block :title="$t('title6')">
<van-cell-group>
<van-field
center
v-model="sms"
:label="$t('sms')"
:placeholder="$t('smsPlaceholder')"
icon="clear"
@click-icon="sms = ''"
>
<van-button slot="button" size="small" type="primary">{{ $t('sendSMS') }}</van-button>
</van-field>
</van-cell-group>
</demo-block>
</demo-section> </demo-section>
</template> </template>
@ -68,8 +88,12 @@ export default {
title3: '禁用输入框', title3: '禁用输入框',
title4: '错误提示', title4: '错误提示',
title5: '高度自适应', title5: '高度自适应',
title6: '插入按钮',
message: '留言', message: '留言',
phone: '手机号', phone: '手机号',
sms: '短信验证码',
sendSMS: '发送验证码',
smsPlaceholder: '请输入短信验证码',
phonePlaceholder: '请输入手机号', phonePlaceholder: '请输入手机号',
messagePlaceholder: '请输入留言', messagePlaceholder: '请输入留言',
inputDisabled: '输入框已禁用', inputDisabled: '输入框已禁用',
@ -80,8 +104,12 @@ export default {
title3: 'Disabled', title3: 'Disabled',
title4: 'Error info', title4: 'Error info',
title5: 'Auto resize', title5: 'Auto resize',
title6: 'Insert button',
message: 'Message', message: 'Message',
phone: 'Phone', phone: 'Phone',
sms: 'SMS',
sendSMS: 'Send SMS',
smsPlaceholder: 'SMS',
phonePlaceholder: 'Phone', phonePlaceholder: 'Phone',
messagePlaceholder: 'Message', messagePlaceholder: 'Message',
inputDisabled: 'Disabled', inputDisabled: 'Disabled',
@ -91,9 +119,11 @@ export default {
data() { data() {
return { return {
sms: '',
value: '', value: '',
password: '', password: '',
username: '', username: '',
username2: '',
message: '', message: '',
phone: '1365577' phone: '1365577'
}; };

View File

@ -60,11 +60,13 @@ Use `error` or `error-message` to show error info
```html ```html
<van-cell-group> <van-cell-group>
<van-field <van-field
v-model="username"
label="Username" label="Username"
placeholder="Username" placeholder="Username"
error error
/> />
<van-field <van-field
v-model="phone"
label="Phone" label="Phone"
placeholder="Phone" placeholder="Phone"
error-message="Invalid phone" error-message="Invalid phone"
@ -88,6 +90,24 @@ Textarea Filed can be auto resize when has `autosize` prop
</van-cell-group> </van-cell-group>
``` ```
#### Insert button
Use button slot to insert button
```html
<van-cell-group>
<van-field
center
v-model="sms"
label="SMS"
placeholder="SMS"
icon="clear"
@click-icon="sms = ''"
>
<van-button slot="button" size="small" type="primary">Send SMS</van-button>
</van-field>
</van-cell-group>
```
### API ### API
Filed support all native properties of input tagsuch as `maxlength``placeholder``readonly``autofocus` Filed support all native properties of input tagsuch as `maxlength``placeholder``readonly``autofocus`
@ -114,3 +134,4 @@ Filed support all native events of input tagsuch as `focus`、`blur`、`keypr
| name | Description | | name | Description |
|-----------|-----------| |-----------|-----------|
| icon | Custom icon | | icon | Custom icon |
| button | Insert button |

View File

@ -62,11 +62,13 @@ Vue.use(Field);
```html ```html
<van-cell-group> <van-cell-group>
<van-field <van-field
v-model="username"
label="用户名" label="用户名"
placeholder="请输入用户名" placeholder="请输入用户名"
error error
/> />
<van-field <van-field
v-model="phone"
label="手机号" label="手机号"
placeholder="请输入手机号" placeholder="请输入手机号"
error-message="手机号格式错误" error-message="手机号格式错误"
@ -90,6 +92,24 @@ Vue.use(Field);
</van-cell-group> </van-cell-group>
``` ```
#### 插入按钮
通过 button slot 可以在输入框尾部插入按钮
```html
<van-cell-group>
<van-field
center
v-model="sms"
label="短信验证码"
placeholder="请输入短信验证码"
icon="clear"
@click-icon="sms = ''"
>
<van-button slot="button" size="small" type="primary">发送验证码</van-button>
</van-field>
</van-cell-group>
```
### API ### API
Filed 默认支持 Input 标签所有的原生属性,比如 `maxlength``placeholder``readonly``autofocus` Filed 默认支持 Input 标签所有的原生属性,比如 `maxlength``placeholder``readonly``autofocus`
@ -115,4 +135,5 @@ Filed 默认支持 Input 标签所有的原生事件,如 `focus`、`blur`、`k
| 名称 | 说明 | | 名称 | 说明 |
|-----------|-----------| |-----------|-----------|
| icon | 自定义icon | | icon | 自定义输入框尾部图标 |
| button | 自定义输入框尾部按钮 |

View File

@ -1,17 +1,14 @@
<template> <template>
<cell <cell
:title="label" :title="label"
:center="center"
:required="required" :required="required"
class="van-field" class="van-field"
:class="{ :class="{
'van-field--has-textarea': type === 'textarea',
'van-field--nolabel': !label,
'van-field--disabled': $attrs.disabled, 'van-field--disabled': $attrs.disabled,
'van-field--error': error, 'van-field--error': error,
'van-field--border': border, 'van-field--min-height': type === 'textarea' && !autosize,
'van-field--autosize': autosize, 'van-field--has-icon': hasIcon
'van-field--has-icon': hasIcon,
'van-hairline--surround': border
}" }"
> >
<textarea <textarea
@ -45,6 +42,9 @@
<icon :name="icon" /> <icon :name="icon" />
</slot> </slot>
</div> </div>
<div class="van-field__button" v-if="$slots.button" slot="extra">
<slot name="button" />
</div>
</cell> </cell>
</template> </template>
@ -66,6 +66,7 @@ export default create({
icon: String, icon: String,
label: String, label: String,
error: Boolean, error: Boolean,
center: Boolean,
border: Boolean, border: Boolean,
required: Boolean, required: Boolean,
autosize: [Boolean, Object], autosize: [Boolean, Object],

View File

@ -75,6 +75,10 @@
} }
} }
&--center {
align-items: center;
}
&__right-icon { &__right-icon {
position: absolute; position: absolute;
top: 50%; top: 50%;

View File

@ -1,10 +1,43 @@
@import './common/var.css'; @import './common/var.css';
.van-field { .van-field {
width: 100%;
.van-cell__title { .van-cell__title {
width: 90px; min-width: 90px;
}
.van-cell__value {
position: relative;
}
&__control {
border: 0;
padding: 0;
display: block;
width: 100%;
resize: none;
box-sizing: border-box;
&:disabled {
opacity: 1;
color: $gray-darker;
background-color: transparent;
}
}
&__icon {
position: absolute;
right: 0;
top: 50%;
padding: 10px 0 10px 10px;
transform: translate3d(0, -50%, 0);
.van-icon {
display: block;
}
}
&__button {
padding-left: 10px;
} }
&__error-message { &__error-message {
@ -13,23 +46,6 @@
text-align: left; text-align: left;
} }
&--has-textarea {
.van-field__control {
min-height: 60px;
}
}
&--nolabel {
.van-cell__title {
display: none;
}
.van-cell__value {
width: 100%;
padding-left: 0;
}
}
&--disabled { &--disabled {
.van-field__control { .van-field__control {
color: $gray-dark; color: $gray-dark;
@ -45,54 +61,15 @@
} }
} }
&--border { &--min-height {
.van-field__control { .van-field__control {
padding-left: 10px; min-height: 60px;
}
&::after {
border-radius: 2px;
}
}
&--autosize {
.van-field__control {
min-height: 0;
} }
} }
&--has-icon { &--has-icon {
.van-field__control { .van-field__control {
width: 90%; padding-right: 20px;
}
}
&__control {
border: 0;
font-size: 14px;
line-height: 24px;
height: 24px;
padding: 0;
display: block;
width: 100%;
resize: none;
&:disabled {
opacity: 1;
color: $gray-darker;
background-color: transparent;
}
}
&__icon {
position: absolute;
right: 0;
top: 50%;
transform: translate3d(0, -50%, 0);
padding: 10px;
.van-icon {
display: block;
} }
} }
} }

View File

@ -19,18 +19,6 @@ describe('Field', () => {
expect(wrapper.hasClass('van-field')).to.be.true; expect(wrapper.hasClass('van-field')).to.be.true;
}); });
it('create a border field', () => {
wrapper = mount(Field, {
propsData: {
type: 'text',
border: true
}
});
expect(wrapper.hasClass('van-field')).to.be.true;
expect(wrapper.hasClass('van-field--border')).to.be.true;
});
it('create a text field with initialize value', (done) => { it('create a text field with initialize value', (done) => {
wrapper = mount(Field, { wrapper = mount(Field, {
propsData: { propsData: {
@ -69,14 +57,12 @@ describe('Field', () => {
it('create a textarea field', (done) => { it('create a textarea field', (done) => {
wrapper = mount(Field, { wrapper = mount(Field, {
propsData: { propsData: {
type: 'textarea', type: 'textarea'
autosize: true
} }
}); });
setTimeout(() => { setTimeout(() => {
expect(wrapper.hasClass('van-field')).to.be.true; expect(wrapper.hasClass('van-field--min-height')).to.be.true;
expect(wrapper.hasClass('van-field--has-textarea')).to.be.true;
done(); done();
}, 50); }, 50);
}); });
@ -93,9 +79,6 @@ describe('Field', () => {
wrapper.vm.value = val; wrapper.vm.value = val;
}); });
expect(wrapper.hasClass('van-field')).to.be.true;
expect(wrapper.hasClass('van-field--autosize')).to.be.true;
const textarea = wrapper.find('.van-field__control')[0]; const textarea = wrapper.find('.van-field__control')[0];
const textareaElement = textarea.element; const textareaElement = textarea.element;
const textAreaDiff = (parseInt(textareaElement.style.paddingBottom, 10) + const textAreaDiff = (parseInt(textareaElement.style.paddingBottom, 10) +
@ -128,9 +111,6 @@ describe('Field', () => {
wrapper.vm.value = val; wrapper.vm.value = val;
}); });
expect(wrapper.hasClass('van-field')).to.be.true;
expect(wrapper.hasClass('van-field--autosize')).to.be.true;
const textarea = wrapper.find('.van-field__control')[0]; const textarea = wrapper.find('.van-field__control')[0];
const textareaElement = textarea.element; const textareaElement = textarea.element;