Skip to content

Commit a14d613

Browse files
docs: add demo
1 parent 4101ad7 commit a14d613

File tree

12 files changed

+268
-252
lines changed

12 files changed

+268
-252
lines changed

.eslintrc.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ module.exports = {
1515
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
1616
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
1717
semi: ["error", "never"],
18-
"@typescript-eslint/ban-ts-ignore": "off"
18+
"@typescript-eslint/ban-ts-ignore": "off",
19+
"@typescript-eslint/no-explicit-any": "off"
1920
},
2021
overrides: [
2122
{

example/App.vue

+3-15
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,17 @@
11
<template>
22
<div id="app">
3-
<img alt="Vue logo" src="./assets/logo.png">
4-
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
3+
<Demo />
54
</div>
65
</template>
76

87
<script lang="ts">
98
import { defineComponent } from 'vue'
10-
import HelloWorld from './components/HelloWorld.vue'
9+
import Demo from './components/Demo.vue'
1110
1211
export default defineComponent({
1312
name: 'App',
1413
components: {
15-
HelloWorld,
14+
Demo,
1615
},
1716
})
1817
</script>
19-
20-
<style>
21-
#app {
22-
font-family: Avenir, Helvetica, Arial, sans-serif;
23-
-webkit-font-smoothing: antialiased;
24-
-moz-osx-font-smoothing: grayscale;
25-
text-align: center;
26-
color: #2c3e50;
27-
margin-top: 60px;
28-
}
29-
</style>

example/components/Demo.vue

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<template>
2+
<Input
3+
label="Username"
4+
icon="fa-user"
5+
v-model="username.value"
6+
:ref="username.ref"
7+
:is-danger="!!username.error"
8+
:error-message="username.error && username.error.message"
9+
/>
10+
<Input
11+
label="Password"
12+
type="password"
13+
icon="fa-key"
14+
v-model="password.value"
15+
:ref="password.ref"
16+
:is-danger="!!password.error"
17+
:error-message="password.error && password.error.message"
18+
/>
19+
<Input
20+
label="Confirm Password"
21+
type="password"
22+
icon="fa-key"
23+
v-model="confirmedPassword.value"
24+
:ref="confirmedPassword.ref"
25+
:is-danger="!!confirmedPassword.error"
26+
:error-message="confirmedPassword.error && confirmedPassword.error.message"
27+
/>
28+
<button class="button is-link" @click="onSubmit">Submit</button>
29+
</template>
30+
31+
<script lang="ts">
32+
import { defineComponent } from 'vue'
33+
import Input from './Input.vue'
34+
import { useForm } from '../../src'
35+
36+
export default defineComponent({
37+
name: 'Demo',
38+
components: {
39+
Input,
40+
},
41+
props: {
42+
modelValue: String,
43+
},
44+
setup() {
45+
const {
46+
useField, validateFields, errorFields, getFieldValues, values,
47+
} = useForm({
48+
defaultValues: {
49+
username: 'Victor',
50+
},
51+
})
52+
const username = useField('username', {
53+
rule: { required: true },
54+
})
55+
const password = useField('password', {
56+
rule: {
57+
required: true, min: 6, max: 10,
58+
},
59+
})
60+
const confirmedPassword = useField('confirmedPassword', {
61+
rule: {
62+
required: true,
63+
validator(rule, value) {
64+
if (!value || value !== (values as any).password) {
65+
return new Error('The two passwords that you entered do not match!')
66+
}
67+
return true
68+
},
69+
},
70+
})
71+
return {
72+
username,
73+
password,
74+
confirmedPassword,
75+
async onSubmit() {
76+
try {
77+
await validateFields()
78+
console.log(getFieldValues())
79+
} catch (error) {
80+
console.log(error)
81+
}
82+
},
83+
errorFields,
84+
}
85+
},
86+
})
87+
</script>

example/components/HelloWorld.vue

-98
This file was deleted.

example/components/Input.vue

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<template>
2+
<div class="field">
3+
<label class="label">{{ label }}</label>
4+
<div class="control has-icons-left has-icons-right">
5+
<input
6+
:class="['input', isDanger ? 'is-danger': '' ]"
7+
type="text"
8+
:value="modelValue"
9+
@input="e => $emit('update:modelValue', e.target.value)"
10+
v-bind="$attrs"
11+
/>
12+
<span class="icon is-small is-left">
13+
<i :class="['fas', icon]"></i>
14+
</span>
15+
<p class="help is-danger">{{errorMessage}}</p>
16+
</div>
17+
</div>
18+
</template>
19+
20+
<script lang="ts">
21+
import { defineComponent } from 'vue'
22+
23+
export default defineComponent({
24+
name: 'Input',
25+
components: {},
26+
props: {
27+
modelValue: String,
28+
label: String,
29+
icon: String,
30+
errorMessage: String,
31+
isDanger: Boolean,
32+
},
33+
computed: {
34+
iconClass(): string {
35+
return this.icon ? `fas ${this.icon}` : ''
36+
},
37+
},
38+
})
39+
</script>

example/components/TestInput.vue

-26
This file was deleted.

package.json

+7-5
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@
33
"version": "0.1.0",
44
"private": true,
55
"scripts": {
6-
"serve": "vue-cli-service serve example/main.ts",
6+
"start": "vue-cli-service serve example/main.ts",
77
"build": "vue-cli-service build",
8-
"test:unit": "vue-cli-service test:unit",
9-
"test:e2e": "vue-cli-service test:e2e",
10-
"lint": "vue-cli-service lint"
8+
"test": "jest --coverage"
119
},
1210
"dependencies": {
1311
"async-validator": "^3.4.0",
@@ -16,7 +14,9 @@
1614
"lodash.merge": "^4.6.2",
1715
"lodash.set": "^4.3.2",
1816
"lodash.setwith": "^4.3.2",
19-
"lodash.topath": "^4.5.2",
17+
"lodash.topath": "^4.5.2"
18+
},
19+
"peerDependencies": {
2020
"vue": "^3.0.0"
2121
},
2222
"devDependencies": {
@@ -41,7 +41,9 @@
4141
"eslint": "^6.7.2",
4242
"eslint-plugin-import": "^2.20.2",
4343
"eslint-plugin-vue": "^7.0.0-0",
44+
"materialize-css": "^1.0.0-rc.2",
4445
"typescript": "~3.9.3",
46+
"vue": "^3.0.1",
4547
"vue-jest": "^5.0.0-0"
4648
}
4749
}

public/index.html

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<meta http-equiv="X-UA-Compatible" content="IE=edge">
66
<meta name="viewport" content="width=device-width,initial-scale=1.0">
77
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
8+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css">
89
<title><%= htmlWebpackPlugin.options.title %></title>
910
</head>
1011
<body>
@@ -13,5 +14,6 @@
1314
</noscript>
1415
<div id="app"></div>
1516
<!-- built files will be auto injected -->
17+
<script defer src="https://use.fontawesome.com/releases/v5.14.0/js/all.js"></script>
1618
</body>
1719
</html>

src/deepValidator.ts

+14-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ const setRule = (rules: Rules, path: any, rule: RuleItem) => {
1919
return pathValue
2020
})
2121
}
22+
23+
export type Errors = {
24+
[key: string]: {
25+
message: string;
26+
field: string;
27+
};
28+
}
29+
2230
const DeepValidator = (rules: Rules = {}) => {
2331
const registerRule = (path: any, rule: RuleItem) => {
2432
setRule(rules, path, rule)
@@ -27,7 +35,11 @@ const DeepValidator = (rules: Rules = {}) => {
2735
try {
2836
return await new Validator(rules).validate(data)
2937
} catch ({ errors, fields }) {
30-
throw fields
38+
const errorObject: Errors = Object.keys(fields).reduce((acc, key) => {
39+
acc[key] = get(fields, [key, 0])
40+
return acc
41+
}, {} as Errors)
42+
throw errorObject
3143
}
3244
}
3345
return {
@@ -41,7 +53,7 @@ const DeepValidator = (rules: Rules = {}) => {
4153
set({}, path, value),
4254
)
4355
} catch ({ fields }) {
44-
throw fields[path]
56+
throw get(fields, [path, 0])
4557
}
4658
},
4759
}

0 commit comments

Comments
 (0)