mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat: add form component
This commit is contained in:
parent
0346b6c4d2
commit
9326ad84f8
@ -15,9 +15,16 @@ const [createComponent, bem] = createNamespace('field');
|
||||
export default createComponent({
|
||||
inheritAttrs: false,
|
||||
|
||||
inject: {
|
||||
vanForm: {
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
|
||||
props: {
|
||||
...cellProps,
|
||||
name: String,
|
||||
rules: Array,
|
||||
error: Boolean,
|
||||
disabled: Boolean,
|
||||
readonly: Boolean,
|
||||
@ -44,6 +51,8 @@ export default createComponent({
|
||||
data() {
|
||||
return {
|
||||
focused: false,
|
||||
validateError: false,
|
||||
validateMessage: '',
|
||||
};
|
||||
},
|
||||
|
||||
@ -56,6 +65,16 @@ export default createComponent({
|
||||
mounted() {
|
||||
this.format();
|
||||
this.$nextTick(this.adjustSize);
|
||||
|
||||
if (this.vanForm) {
|
||||
this.vanForm.fields.push(this);
|
||||
}
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
if (this.vanForm) {
|
||||
this.vanForm.fields = this.vanForm.fields.fiilter(item => item !== this);
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
@ -106,6 +125,23 @@ export default createComponent({
|
||||
}
|
||||
},
|
||||
|
||||
// @exposed-api
|
||||
validate() {
|
||||
if (!this.rules) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !this.rules.some(rule => {
|
||||
if (rule.required && !this.value) {
|
||||
this.validateError = true;
|
||||
this.validateMessage = rule.message;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
format(target = this.$refs.input) {
|
||||
if (!target) {
|
||||
return;
|
||||
@ -316,6 +352,18 @@ export default createComponent({
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
genMessage() {
|
||||
const message = this.errorMessage || this.validateMessage;
|
||||
|
||||
if (message) {
|
||||
return (
|
||||
<div class={bem('error-message', this.errorMessageAlign)}>
|
||||
{message}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
render() {
|
||||
@ -343,7 +391,7 @@ export default createComponent({
|
||||
titleClass={[bem('label', labelAlign), this.labelClass]}
|
||||
arrowDirection={this.arrowDirection}
|
||||
class={bem({
|
||||
error: this.error,
|
||||
error: this.error || this.validateError,
|
||||
[`label-${labelAlign}`]: labelAlign,
|
||||
'min-height': this.type === 'textarea' && !this.autosize,
|
||||
})}
|
||||
@ -365,11 +413,7 @@ export default createComponent({
|
||||
)}
|
||||
</div>
|
||||
{this.genWordLimit()}
|
||||
{this.errorMessage && (
|
||||
<div class={bem('error-message', this.errorMessageAlign)}>
|
||||
{this.errorMessage}
|
||||
</div>
|
||||
)}
|
||||
{this.genMessage()}
|
||||
</Cell>
|
||||
);
|
||||
},
|
||||
|
30
src/form/README.md
Normal file
30
src/form/README.md
Normal file
@ -0,0 +1,30 @@
|
||||
# Form
|
||||
|
||||
### Install
|
||||
|
||||
```js
|
||||
import Vue from 'vue';
|
||||
import { Form } from 'vant';
|
||||
|
||||
Vue.use(Form);
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
|------|------|------|------|
|
||||
|
||||
### Events
|
||||
|
||||
| Event | Description | Arguments |
|
||||
|
||||
### Slots
|
||||
|
||||
| Name | Description |
|
||||
|------|------|
|
31
src/form/README.zh-CN.md
Normal file
31
src/form/README.zh-CN.md
Normal file
@ -0,0 +1,31 @@
|
||||
# Form 表单
|
||||
|
||||
### 引入
|
||||
|
||||
```js
|
||||
import Vue from 'vue';
|
||||
import { Form } from 'vant';
|
||||
|
||||
Vue.use(Form);
|
||||
```
|
||||
|
||||
## 代码演示
|
||||
|
||||
### 基础用法
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|------|------|------|------|
|
||||
|
||||
### Events
|
||||
|
||||
| 事件名 | 说明 | 回调参数 |
|
||||
|------|------|------|
|
||||
|
||||
### Slots
|
||||
|
||||
| 名称 | 说明 |
|
||||
|------|------|
|
58
src/form/demo/index.vue
Normal file
58
src/form/demo/index.vue
Normal file
@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<demo-section>
|
||||
<demo-block :title="$t('basicUsage')">
|
||||
<van-form @submit="onSubmit">
|
||||
<van-field
|
||||
v-model="username"
|
||||
name="username"
|
||||
label="username"
|
||||
:rules="[{ required: true, message: 'username is required' }]"
|
||||
placeholder="username"
|
||||
/>
|
||||
<van-field
|
||||
v-model="password"
|
||||
type="password"
|
||||
name="password"
|
||||
label="password"
|
||||
:rules="[{ required: true, message: 'password is required' }]"
|
||||
placeholder="password"
|
||||
/>
|
||||
<van-field name="agree" label="agree">
|
||||
<van-checkbox v-model="agree" slot="input" shape="square" />
|
||||
</van-field>
|
||||
<van-button type="primary">submit</van-button>
|
||||
</van-form>
|
||||
</demo-block>
|
||||
</demo-section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
i18n: {
|
||||
'zh-CN': {},
|
||||
'en-US': {},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
username: '',
|
||||
password: '',
|
||||
agree: true,
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
onSubmit() {},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../style/var';
|
||||
|
||||
.demo-form {
|
||||
.van-button {
|
||||
margin: 15px 0 0 15px;
|
||||
}
|
||||
}
|
||||
</style>
|
36
src/form/index.js
Normal file
36
src/form/index.js
Normal file
@ -0,0 +1,36 @@
|
||||
// Utils
|
||||
import { createNamespace } from '../utils';
|
||||
|
||||
const [createComponent, bem] = createNamespace('form');
|
||||
|
||||
export default createComponent({
|
||||
provide() {
|
||||
return {
|
||||
vanForm: this,
|
||||
};
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
fields: [],
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
onSubmit(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const results = this.fields.map(item => item.validate());
|
||||
|
||||
console.log(results);
|
||||
},
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<form class={bem()} onSubmit={this.onSubmit}>
|
||||
{this.slots()}
|
||||
</form>
|
||||
);
|
||||
},
|
||||
});
|
35
src/form/test/__snapshots__/demo.spec.js.snap
Normal file
35
src/form/test/__snapshots__/demo.spec.js.snap
Normal file
@ -0,0 +1,35 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders demo correctly 1`] = `
|
||||
<div>
|
||||
<div>
|
||||
<form class="van-form">
|
||||
<div class="van-cell van-field">
|
||||
<div class="van-cell__title van-field__label"><span>username</span></div>
|
||||
<div class="van-cell__value">
|
||||
<div class="van-field__body"><input type="text" name="username" placeholder="username" class="van-field__control"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="van-cell van-field">
|
||||
<div class="van-cell__title van-field__label"><span>password</span></div>
|
||||
<div class="van-cell__value">
|
||||
<div class="van-field__body"><input type="password" name="password" placeholder="password" class="van-field__control"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="van-cell van-field">
|
||||
<div class="van-cell__title van-field__label"><span>agree</span></div>
|
||||
<div class="van-cell__value">
|
||||
<div class="van-field__body">
|
||||
<div class="van-field__control">
|
||||
<div role="checkbox" tabindex="0" aria-checked="false" class="van-checkbox">
|
||||
<div class="van-checkbox__icon van-checkbox__icon--square"><i class="van-icon van-icon-success">
|
||||
<!----></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> <button class="van-button van-button--primary van-button--normal"><span class="van-button__text">submit</span></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
4
src/form/test/demo.spec.js
Normal file
4
src/form/test/demo.spec.js
Normal file
@ -0,0 +1,4 @@
|
||||
import Demo from '../demo';
|
||||
import { snapshotDemo } from '../../../test/demo';
|
||||
|
||||
snapshotDemo(Demo);
|
1
src/form/test/index.spec.js
Normal file
1
src/form/test/index.spec.js
Normal file
@ -0,0 +1 @@
|
||||
// import { mount } from '../../../test';
|
Loading…
x
Reference in New Issue
Block a user