├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ └── npm-publish-github-packages.yml
├── .gitignore
├── .npmignore
├── .travis.yml
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── build
├── vuejs-form.js
└── vuejs-form.min.js
├── bundler
├── badges.md
├── bundle.js
├── change_log.md
├── contribute.md
├── extend.md
├── header.md
├── highlight.md
├── installation.md
├── license.md
├── macros.md
├── markdown.js
├── purpose.md
├── security_vulnerabilities.md
├── setup.md
├── utilization.md
├── validator.md
├── versioning.md
├── vue.md
└── vuejs-form-purpose-statement.png
├── code_of_conduct.md
├── dist
├── helpers
│ ├── accessor.js
│ ├── dataGet.js
│ ├── dataSet.js
│ ├── exists.js
│ ├── fieldsOf.js
│ ├── isEmpty.js
│ ├── nestedValue.js
│ ├── setKeys.js
│ ├── setProperties.js
│ └── variadic.js
├── index.js
└── methods
│ ├── all.js
│ ├── anyFilled.js
│ ├── boolean.js
│ ├── build.js
│ ├── empty.js
│ ├── except.js
│ ├── extend.js
│ ├── fill.js
│ ├── filled.js
│ ├── forceLocalMacro.js
│ ├── forceMacro.js
│ ├── forget.js
│ ├── has.js
│ ├── hasAny.js
│ ├── input.js
│ ├── keys.js
│ ├── localMacro.js
│ ├── macro.js
│ ├── make.js
│ ├── missing.js
│ ├── only.js
│ ├── override.js
│ ├── proxy.js
│ ├── set.js
│ ├── toArray.js
│ ├── use.js
│ └── wrap.js
├── docs
├── .vuepress
│ └── config.js
├── README.md
└── api
│ ├── all.md
│ ├── boolean.md
│ ├── empty.md
│ ├── except.md
│ ├── fill.md
│ ├── filled.md
│ ├── forceMacro.md
│ ├── forget.md
│ ├── has.md
│ ├── hasAny.md
│ ├── input.md
│ ├── keys.md
│ ├── macro.md
│ ├── make.md
│ ├── missing.md
│ ├── only.md
│ ├── set.md
│ ├── toArray.md
│ └── wrap.md
├── mix-manifest.json
├── package.json
├── src
├── helpers
│ ├── accessor.js
│ ├── dataGet.js
│ ├── dataSet.js
│ ├── exists.js
│ ├── fieldsOf.js
│ ├── isEmpty.js
│ ├── nestedValue.js
│ └── variadic.js
├── index.js
└── methods
│ ├── all.js
│ ├── anyFilled.js
│ ├── boolean.js
│ ├── build.js
│ ├── empty.js
│ ├── except.js
│ ├── extend.js
│ ├── fill.js
│ ├── filled.js
│ ├── forceLocalMacro.js
│ ├── forceMacro.js
│ ├── forget.js
│ ├── has.js
│ ├── hasAny.js
│ ├── input.js
│ ├── keys.js
│ ├── localMacro.js
│ ├── macro.js
│ ├── make.js
│ ├── missing.js
│ ├── only.js
│ ├── proxy.js
│ ├── set.js
│ ├── toArray.js
│ ├── use.js
│ └── wrap.js
└── test
├── methods
├── accessor_test.js
├── all_test.js
├── anyFilled_test.js
├── boolean_test.js
├── empty_test.js
├── except_test.js
├── fill_test.js
├── filled_test.js
├── forceLocal_macro.test.js
├── forceMacro_test.js
├── forget_test.js
├── hasAny_test.js
├── has_test.js
├── input_test.js
├── keys_test.js
├── localMacro_test.js
├── macro_test.js
├── missing_test.js
├── only_test.js
├── set_test.js
├── toArray_test.js
├── use_test.js
└── wrap_test.js
└── tests.js
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/workflows/npm-publish-github-packages.yml:
--------------------------------------------------------------------------------
1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages
3 |
4 | name: Node.js Package
5 |
6 | on:
7 | release:
8 | types: [created]
9 |
10 | jobs:
11 | build:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v2
15 | - uses: actions/setup-node@v2
16 | with:
17 | node-version: 16
18 | - run: npm ci
19 | - run: npm test
20 |
21 | publish-gpr:
22 | needs: build
23 | runs-on: ubuntu-latest
24 | permissions:
25 | contents: read
26 | packages: write
27 | steps:
28 | - uses: actions/checkout@v2
29 | - uses: actions/setup-node@v2
30 | with:
31 | node-version: 16
32 | registry-url: https://npm.pkg.github.com/
33 | - run: npm ci
34 | - run: npm publish
35 | env:
36 | NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | node_modules
3 | .npm-debug.log
4 | npm-debug.log
5 | test/benchmark.js
6 | test/implementations.js
7 | coverage
8 | .nyc_output
9 | .DS_Store
10 | package-lock.json
11 | docs/.vuepress/dist/*
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .idea
2 | test
3 | coverage
4 | .nyc_output
5 | npm-debug.log
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '12'
4 | - '10'
5 | - '8'
6 | script:
7 | - npm run coverage
8 |
9 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | ## Change Log
4 |
5 | ---
6 | - [Release 1.3.0 (Minor)](#release-130)
7 | - [Release 1.2.9 (Minor)](#release-129)
8 | - [Release 1.2.8 (Minor)](#release-128)
9 | - [Release 1.2.7 (Minor)](#release-127)
10 | - [Release 1.2.6 (Minor)](#release-126)
11 | - [Release 1.2.5 (Minor)](#release-125)
12 | - [Release 1.2.4 (Minor)](#release-124)
13 | - [Release 1.2.3 (Minor)](#release-123)
14 | - [Release 1.2.2 (Minor)](#release-122)
15 | - [Release 1.2.1 (Minor)](#release-121)
16 | - [Release 1.2.0 (Major)](#release-120)
17 | - [Release 1.1.1](#release-111)
18 | - [Release 1.1.0](#release-110)
19 |
20 | ---
21 |
22 | ### Release 1.3.0
23 |
24 | ---
25 | - Fixed [first keypress not working bug](https://github.com/zhorton34/vuejs-form/issues/20)
26 |
27 | ---
28 |
29 | ---
30 |
31 | ### Release 1.2.9
32 |
33 | ---
34 | - Removed unused documentation assets
35 |
36 | ---
37 |
38 | ### Release 1.2.8
39 |
40 | ---
41 | - date validation rule
42 | - date equals validation rule
43 | - before (date) validation rule
44 | - before_or_equal (date) validation rule
45 | - after (date) validation rule
46 | - after_or_equal (date) validation rule
47 | - less_than (numeric) validation rule
48 | - greater_than (numeric) validation rule
49 | - lte (less than or equal numeric) validation rule
50 | - gte (greater than or equal numeric) validation rule
51 |
52 |
53 | ---
54 |
55 | ### Release 1.2.7
56 |
57 | ---
58 | - overwrite method outdated in place of forceMacro
59 | - macro method refactored, in depth testing and documentation
60 | - localMacro method created, in depth testing, and documentation
61 | - forceMacro method created, in depth testing, and documentation
62 | - forceLocalMacro method created, in depth testing, and documentation
63 | - Form Api is macro capable
64 | - Validator Api is macro capable
65 | - Error Messages Api is macro capable
66 | - Macro capabilities documentation for each macro type
67 |
68 | ---
69 |
70 | ### Release 1.2.6
71 |
72 | ---
73 |
74 | - Beautified Docs A Bit
75 | - Vuejs Validations Ref Updated
76 | - MessageBag Added to Package Exports
77 | - MessageBagFactory Added to Package Exports
78 | - Error Messages Api Documentation Readme Updated
79 |
80 | ---
81 |
82 | ### Release 1.2.5
83 |
84 | ---
85 |
86 | - Updated Cdn Documented Link Examples To Reference Latest Instead Of Specific Version
87 |
88 |
89 | ---
90 |
91 | ### Release 1.2.4
92 |
93 | ---
94 |
95 | - Updated Purpose.md Documentation To Us Image Notepad Message
96 |
97 |
98 | ---
99 |
100 | ### Release 1.2.3
101 |
102 | ---
103 |
104 | - Updated Change Log Release Link References
105 | - Updated Purpose.md Documentation To Us Image Notepad Message
106 |
107 |
108 | ---
109 |
110 | ### Release 1.2.2
111 |
112 | ---
113 |
114 | - Updated Document Headers
115 | - Removed api.md section of Documentation
116 | - Removed bloated docs from setup.md
117 | - Added cdn installation and npm installation examples
118 |
119 | ---
120 |
121 | ### Release 1.2.1
122 |
123 | ---
124 |
125 | - Updated Documentation To Start With "Purpose" Of Package
126 | - Removed Documentation Content From Header.md
127 | - Caught Change Log Up
128 |
129 | ---
130 |
131 | ### Release 1.2.0
132 |
133 | ---
134 |
135 | - Documentation Updated
136 | - First Official Stable Release
137 | - Semantic Versioning Officially Supported
138 |
139 |
140 |
141 | ---
142 |
143 | ### Release 1.1.1
144 |
145 | ---
146 |
147 | - CDN Setup
148 | - CDN Documentation Added
149 | - Added markdown.js for internal markup creation
150 | - Added Security Vulnerabilities Documentation
151 | - Added Versioning To Documentation
152 | - Added Code Of Conduct To Documentation
153 | - Extensive Documentation
154 | - Security Vulnerabilities Docs
155 | - Code Of Conduct Docs
156 | - Markdown Support Class
157 | - highlight.md
158 | - Versioning implementation documented
159 |
160 |
161 |
162 | ---
163 |
164 | ### Release 1.1.0
165 |
166 | ---
167 |
168 | - "form.getErrors()" replaced with "form.errors()"
169 | - "form.getValidator()" replaced with "form.validator()"
170 | - "vuejs-validators" setup as dev dependency
171 | - "ValidatableForm" Export ~ (Ex: const { ValidatableForm } = require('vuejs-form'))
172 | - Default import is ValidatableForm (Ex: import form from 'vuejs-form' has validator || import { form } from 'vuejs-form' does not have validator)
173 |
174 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ### Code Of Conduct
2 |
3 | The Clean Code Studio code of conduct is derived from Laravel code of of conduct. Any violations
4 | of the code of conduct may be reported to Zachary Horton (zak@cleancode.studio)
5 |
6 | - Participants will be tolerant of opposing views.
7 |
8 | - Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
9 |
10 | - When interpreting the words and actions of others, participants should always assume good intentions.
11 |
12 | - Behavior that can be reasonably considered harassment will not be tolerated.
13 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contribute
2 |
3 | PRs are welcomed to this project.
4 | If you want to improve the vuejs-form library, add
5 | functionality or improve the docs please feel free to submit a PR.
6 |
7 |
8 | Clean Code Studio
9 | Clean Code Studio ~ Simplify
10 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Zak Horton
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/bundler/badges.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/zhorton34/vuejs-form/builds)
2 | [](http://badge.fury.io/js/vuejs-form)
3 | [](http://badge.fury.io/js/vuejs-form)
4 | [](http://makeapullrequest.com)
5 | [](https://github.com/zhorton34/vuejs-form/blob/master/package.json)
6 | [](http://badge.fury.io/js/vuejs-form)
7 | [](http://hits.dwyl.com/zhorton34/vuejs-form)
8 | [](https://github.com/ellerbrock/open-source-badges/)
9 | [](https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity)
--------------------------------------------------------------------------------
/bundler/bundle.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | const { readFileSync, readdirSync, writeFileSync } = require('fs');
5 |
6 | const methods = readdirSync('docs/api', 'utf-8');
7 | const tableOfContents = methods.map((file) => `- [${file.replace('.md', '')}](#${file.replace('.md', '').toLowerCase()}`).join('\n');
8 | const methodDocumentation = methods.map((file) => {
9 | let content = readFileSync(`docs/api/${file}`, 'utf-8');
10 |
11 | const lines = content.split('\n');
12 |
13 | lines[0] = `###${lines[0]}`;
14 | lines.pop();
15 | lines.pop();
16 |
17 | content = lines.join('\n');
18 | content = content.replace(/(\r\n|\r|\n){2,}/g, '$1\n');
19 |
20 | return content;
21 | }).join('\n\n');
22 |
23 | const bundle = file => readFileSync(`bundler/${file}.md`, 'utf-8');
24 | const ReadMe = (content = []) => writeFileSync('README.md', content.join('\n\n'));
25 | const ChangeLog = (content = []) => writeFileSync('CHANGELOG.md', content.join('\n\n'));
26 |
27 | ChangeLog([bundle('change_log')]);
28 | ReadMe([
29 | ...['badges', 'purpose', 'header', 'installation', 'highlight', 'vue', 'validator'].map(bundle),
30 | ...[tableOfContents, methodDocumentation],
31 | ...['extend', 'macros', 'utilization'].map(bundle),
32 |
33 | ...['contribute', 'security_vulnerabilities', 'change_log', 'versioning', 'license'].map(bundle),
34 | ]);
35 |
36 |
--------------------------------------------------------------------------------
/bundler/change_log.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | ## Change Log
4 |
5 | ---
6 | - [Release 1.3.0 (Minor)](#release-130)
7 | - [Release 1.2.9 (Minor)](#release-129)
8 | - [Release 1.2.8 (Minor)](#release-128)
9 | - [Release 1.2.7 (Minor)](#release-127)
10 | - [Release 1.2.6 (Minor)](#release-126)
11 | - [Release 1.2.5 (Minor)](#release-125)
12 | - [Release 1.2.4 (Minor)](#release-124)
13 | - [Release 1.2.3 (Minor)](#release-123)
14 | - [Release 1.2.2 (Minor)](#release-122)
15 | - [Release 1.2.1 (Minor)](#release-121)
16 | - [Release 1.2.0 (Major)](#release-120)
17 | - [Release 1.1.1](#release-111)
18 | - [Release 1.1.0](#release-110)
19 |
20 | ---
21 |
22 | ### Release 1.3.0
23 |
24 | ---
25 | - Fixed [first keypress not working bug](https://github.com/zhorton34/vuejs-form/issues/20)
26 |
27 | ---
28 |
29 | ---
30 |
31 | ### Release 1.2.9
32 |
33 | ---
34 | - Removed unused documentation assets
35 |
36 | ---
37 |
38 | ### Release 1.2.8
39 |
40 | ---
41 | - date validation rule
42 | - date equals validation rule
43 | - before (date) validation rule
44 | - before_or_equal (date) validation rule
45 | - after (date) validation rule
46 | - after_or_equal (date) validation rule
47 | - less_than (numeric) validation rule
48 | - greater_than (numeric) validation rule
49 | - lte (less than or equal numeric) validation rule
50 | - gte (greater than or equal numeric) validation rule
51 |
52 |
53 | ---
54 |
55 | ### Release 1.2.7
56 |
57 | ---
58 | - overwrite method outdated in place of forceMacro
59 | - macro method refactored, in depth testing and documentation
60 | - localMacro method created, in depth testing, and documentation
61 | - forceMacro method created, in depth testing, and documentation
62 | - forceLocalMacro method created, in depth testing, and documentation
63 | - Form Api is macro capable
64 | - Validator Api is macro capable
65 | - Error Messages Api is macro capable
66 | - Macro capabilities documentation for each macro type
67 |
68 | ---
69 |
70 | ### Release 1.2.6
71 |
72 | ---
73 |
74 | - Beautified Docs A Bit
75 | - Vuejs Validations Ref Updated
76 | - MessageBag Added to Package Exports
77 | - MessageBagFactory Added to Package Exports
78 | - Error Messages Api Documentation Readme Updated
79 |
80 | ---
81 |
82 | ### Release 1.2.5
83 |
84 | ---
85 |
86 | - Updated Cdn Documented Link Examples To Reference Latest Instead Of Specific Version
87 |
88 |
89 | ---
90 |
91 | ### Release 1.2.4
92 |
93 | ---
94 |
95 | - Updated Purpose.md Documentation To Us Image Notepad Message
96 |
97 |
98 | ---
99 |
100 | ### Release 1.2.3
101 |
102 | ---
103 |
104 | - Updated Change Log Release Link References
105 | - Updated Purpose.md Documentation To Us Image Notepad Message
106 |
107 |
108 | ---
109 |
110 | ### Release 1.2.2
111 |
112 | ---
113 |
114 | - Updated Document Headers
115 | - Removed api.md section of Documentation
116 | - Removed bloated docs from setup.md
117 | - Added cdn installation and npm installation examples
118 |
119 | ---
120 |
121 | ### Release 1.2.1
122 |
123 | ---
124 |
125 | - Updated Documentation To Start With "Purpose" Of Package
126 | - Removed Documentation Content From Header.md
127 | - Caught Change Log Up
128 |
129 | ---
130 |
131 | ### Release 1.2.0
132 |
133 | ---
134 |
135 | - Documentation Updated
136 | - First Official Stable Release
137 | - Semantic Versioning Officially Supported
138 |
139 |
140 |
141 | ---
142 |
143 | ### Release 1.1.1
144 |
145 | ---
146 |
147 | - CDN Setup
148 | - CDN Documentation Added
149 | - Added markdown.js for internal markup creation
150 | - Added Security Vulnerabilities Documentation
151 | - Added Versioning To Documentation
152 | - Added Code Of Conduct To Documentation
153 | - Extensive Documentation
154 | - Security Vulnerabilities Docs
155 | - Code Of Conduct Docs
156 | - Markdown Support Class
157 | - highlight.md
158 | - Versioning implementation documented
159 |
160 |
161 |
162 | ---
163 |
164 | ### Release 1.1.0
165 |
166 | ---
167 |
168 | - "form.getErrors()" replaced with "form.errors()"
169 | - "form.getValidator()" replaced with "form.validator()"
170 | - "vuejs-validators" setup as dev dependency
171 | - "ValidatableForm" Export ~ (Ex: const { ValidatableForm } = require('vuejs-form'))
172 | - Default import is ValidatableForm (Ex: import form from 'vuejs-form' has validator || import { form } from 'vuejs-form' does not have validator)
173 |
174 |
--------------------------------------------------------------------------------
/bundler/contribute.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | ## Contribute
4 |
5 | ---
6 |
7 | PRs are welcomed to this project.
8 | If you want to improve the vuejs-form library, add
9 | functionality or improve the docs please feel free to submit a PR.
10 |
--------------------------------------------------------------------------------
/bundler/extend.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | ## Extend Api
4 |
5 | ---
6 |
7 | Extend and append functionality to just about every single major service this package provides
8 |
9 | - [Extend Form Using Macros](#extend-form-using-macros)
10 | - [Extend Validator Using Macros](#extend-validator-using-macros)
11 | - [Extend Error Messages Bag Using Macros](#extend-error-messages-api)
12 | - [Add Custom Error Messages](#extending-custom-error-messages)
13 | - [Create Custom Validation Rule](#extending-custom-rules---single-rule)
14 | - [Create Custom Validation Rules](#extending-custom-rules---multiple-rules)
15 | - [Extend Into Multi Step Form Example](#extend-form-into-multi-step-form-not-tested-but-good-base-to-provide-some-ideas)
16 |
17 | #### Extend Form Using Macros
18 | ```javascript
19 | const form = require('vuejs-form');
20 |
21 | form().macro('shortcut', () => {
22 | return this.validate().errors().list();
23 | });
24 |
25 | let example = form({ name: '' }).rules({ name: 'required' });
26 |
27 | example.shortcut();
28 | // Output: ['Name is a required field'];
29 | ```
30 |
31 | #### Extend Validator Using Macros
32 | ```javascript
33 | const { form, validator } = require('vuejs-form');
34 |
35 | validator().macro('translate', ({ dictionary, locale }) => {
36 | if (!Object.keys(dictionary).includes(locale)) {
37 | console.warn(`Translation dictionary does not include passed ${locale}`);
38 |
39 | return this;
40 | }
41 |
42 | const language = Object.keys(this.messages);
43 | const dictionary_words = key => Object.keys(dictionary[locale]).includes(key);
44 | language.filter(dictionary_words).forEach(key => { this.messages[key] = dictionary[`${locale}.${key}`] });
45 |
46 | return this;
47 | });
48 |
49 | let example = form({ name: '' }).rules({ name: 'required' });
50 |
51 | let locale = 'ru';
52 | let dictionary = { ru: { email: "Эл.почта" } };
53 |
54 | example.validator().translate({ locale, dictionary });
55 | ```
56 |
57 |
58 | ---
59 |
60 | #### Extending Error Messages Api
61 |
62 | ---
63 |
64 | ---
65 |
66 | ##### Error Bag Macro
67 |
68 | ---
69 | Adds custom method on form error bag instance
70 |
71 | ```js
72 | let example = form(data).rules(rules);
73 |
74 | let example.errors().macro('count', function () {
75 | return this.list().length;
76 | });
77 |
78 |
79 | // example.errors().count() === example.errors().list().length
80 | ```
81 |
82 |
83 | ---
84 |
85 | ##### Error Bag ForceMacro
86 |
87 | ---
88 | Allows you to overwrite pre-defined macro and over write core error message bag functions (Use With Caution)
89 |
90 | ```js
91 | let example = form({ name: '' }).rules({ name: 'required|min:3' }).validate();
92 |
93 | example.errors().get('name'); // Outputs: "Name is a required field"
94 |
95 | example.errors().forceMacro('get', function (field) {
96 | if (this.has(field)) {
97 | return this.list(field).join(', ') + '.';
98 | }
99 | });
100 |
101 | example.errors().get('name'); // Outputs: "Name is a required field, name must have at least 3 characters."
102 | ```
103 |
104 | #### Extending: Custom Error Messages
105 | - This has nothing to do with the error messages Api
106 | - These are the literal string output a rule message will display when it fails
107 | - Here we'll customize error messages for specific rules on any given field
108 |
109 | - Globally, each rule provides a default error message
110 | - Easily override rule's default error message
111 | - Simply pass 'messages' to our validator
112 | - Only override messages you want to
113 |
114 | ```javascript
115 | let data = { name: '', email: '' };
116 |
117 | let rules = {
118 | name: ['min:3', 'max:12', 'string', 'required'],
119 | email: ['email', 'required']
120 | };
121 |
122 | let customMessages = {
123 | 'name.min': 'Whoops! :attribute is less than :min characters',
124 | 'name.required': 'Wha oh, doesnt look like there any value for your :attribute field',
125 |
126 | 'email.email': 'Really? Email is called Email...it has to be an email...',
127 | };
128 |
129 | form(data).rules(rules).messages(customMessages).validate().errors().all();
130 | ```
131 |
132 | #### Extending: Custom Rules
133 | > Add Your Own Validation Rules
134 |
135 | - Easily add, or override, validation rules
136 | - Add a group of rules at a time
137 | - Add a single rule add a time
138 |
139 | #### Extending: Custom Rules - Single Rule
140 | > form().validator().extend(rule_name, [message, rule])`
141 | ```js
142 | let example = form({ name: 'timmy' }).rules({ name: 'uppercase' });
143 |
144 | example.validator().extend('uppercase', [
145 | ':attribute must be uppercase',
146 | ({ value, validator, parameters }) => value === value.toUpperCase(),
147 | ]);
148 |
149 | // true
150 | example.validate().errors().has('name');
151 |
152 | // "Name must be uppercase"
153 | example.errors().get('name');
154 | ```
155 |
156 | #### Extending: Custom Rules - multiple rules
157 | > `form.validator().extend({ first: [message, rule], second: [message, rule], etc... })`
158 | ```js
159 | let example = form({ name: '' }).rules({ name: ['required_with:last_name', 'required' ] });
160 |
161 | example.validator().extend({
162 | uppercase: [
163 | ':attribute must be uppercase',
164 | ({ value }) => value === value.toUpperCase(),
165 | ],
166 | not_uppercase: [
167 | ':attribute must not be uppercase',
168 | ({ value }) => value !== value.toUpperCase()
169 | ],
170 | required_without: [
171 | ':attribute is only required when form is missing :required_without field',
172 | ({ validator, parameters }) => !Object.keys(validator.data).includes(parameters[0])
173 | ],
174 | required_with: [
175 | ':attribute is required with the :required_with field',
176 | ({ validator, parameters }) => Object.keys(validator.data).includes(parameters[0])
177 | ],
178 | });
179 | ```
180 |
181 | #### Extend Form Into Multi Step Form (Not tested, but good base to provide some ideas)
182 | - Not actually tested outside of these docs, but solid starting point
183 |
184 | ```html
185 |
186 |
187 |
188 | Step {{ multi.steps().currentStep }} of {{ multi.steps().count() }}
189 |
190 |
191 |
192 |
193 |
194 |
197 |
198 |
201 |
202 |
205 |
206 |
207 | ```
208 |
209 | ```javascript
210 |
211 | const MultiStep = function (form) {
212 | this.sections = {};
213 | this.currentStep = 0;
214 |
215 | this.parent = function () {
216 | return form;
217 | };
218 |
219 | this.current = function () {
220 | if (this.has(this.currentStep)) {
221 | return this.get(this.currentStep);
222 | } else {
223 | console.error("No current step found");
224 | }
225 | };
226 |
227 | this.currentComponent = function () {
228 | return this.current().component_is
229 | };
230 | this.count = function () {
231 | return this.list().length;
232 | };
233 |
234 | this.travel = function (to) {
235 | if (this.has(to)) {
236 | this.currentStep = to;
237 |
238 | return this.current();
239 | } else {
240 | return console.error(`form step ${to} not found`);
241 | }
242 | };
243 |
244 | this.prev = function () {
245 | if (!this.isFirst()) {
246 | this.currentStep = this.currentStep - 1;
247 |
248 | return this.current();
249 | } else {
250 | console.error('already on the very first step')
251 | }
252 | };
253 |
254 |
255 | this.next = function () {
256 | if (!this.isLast()) {
257 | this.currentStep = this.currentStep + 1;
258 |
259 | return this.current();
260 | } else {
261 | console.log('last step')
262 | }
263 | };
264 |
265 | this.hasPrev = function () {
266 | return this.has(this.currentStep + 1);
267 | };
268 |
269 | this.hasCurrent = function () {
270 | return this.has(this.currentStep);
271 | };
272 |
273 | this.isFirst = function () {
274 | return this.hasCurrent() && !this.hasPrev()
275 | };
276 |
277 | this.isLast = function () {
278 | return this.hasCurrent() && !this.hasNext();
279 | };
280 |
281 | this.hasNext = function () {
282 | return this.has(this.currentStep + 1)
283 | };
284 |
285 | this.any = function () {
286 | const isEmpty = value => ([
287 | value === null || value === '',
288 | Array.isArray(value) && value.length === 0,
289 | typeof value === 'object' && Object.keys(value).length === 0
290 | ].includes(true));
291 |
292 | return !isEmpty(this.list());
293 | };
294 |
295 | this.has = function (group) {
296 | return Object.keys(this.sections).includes(group)
297 | && this.sections[group].length > 0
298 | };
299 |
300 | this.all = function () {
301 | return this.sections;
302 | };
303 |
304 | this.list = function (group = false) {
305 | return group
306 | ? this.sections[group]
307 | : Object.keys(this.sections)
308 | .map(group => this.sections[group])
309 | .reduce((list, groups) => [ ...list, ...groups ], []);
310 | };
311 |
312 | this.get = function (group) {
313 | if (this.has(group)) {
314 | return this.sections[group][0];
315 | }
316 | };
317 |
318 | this.add = function(group, item) {
319 | this.sections[group] = Array.isArray(this.sections[group])
320 | ? this.sections[group]
321 | : [];
322 |
323 | this.sections[group].push(item);
324 |
325 | return this;
326 | };
327 |
328 | this.set = function (group, items = []) {
329 | if (typeof items === 'object') {
330 | this.sections = items;
331 | } else {
332 | this.sections[group] = items;
333 | }
334 | };
335 |
336 | this.forget = function (group) {
337 | if (typeof group === 'undefined') {
338 | this.sections = {};
339 | } else {
340 | this.sections[group] = [];
341 | }
342 | };
343 | };
344 |
345 |
346 | const steppable = function (form = {}) {
347 | return new MultiStep(validator);
348 | };
349 |
350 | form().macro('multiple', () => {
351 | this.steppables = steppable(this);
352 |
353 | this.steps = function () {
354 | return this.steppables;
355 | };
356 |
357 | this.first = function () {
358 | return this.steps().get('0')
359 | }
360 |
361 | this.last = function () {
362 | return this.steps().list(this.steps().count() - 1);
363 | };
364 |
365 | this.current = function () {
366 | return this.steps().current();
367 | };
368 |
369 |
370 | return this;
371 | });
372 |
373 | form().multiple().steps();
374 |
375 |
376 | /** Use macro to extend form and append vue component instance to each form step **/
377 | form().macro('hasComponent', () => typeof this.component_is !== 'undefined');
378 | form().macro('getComponent', () => {
379 | this.hasComponent() ? this.component_is : `No Component Registered On This Form Instance
`
380 | });
381 |
382 | form().macro('is', (vue_instance) => {
383 | this.component_is = vue_instance;
384 |
385 | return this;
386 | });
387 |
388 | form().multiple().steps();
389 |
390 | const { name_fields, password_fields, final_step } = require('./components/forms/steps/index.js');
391 |
392 | let multi = form({}).multiple();
393 |
394 | multi.steps().add(0,
395 | form({
396 | last_name: '',
397 | first_name: ''
398 | })
399 | .rules({
400 | last_name: ['required', 'min:3', 'string', 'different:first_name'],
401 | first_name: ['required', 'min:3', 'string', 'different:last_name']
402 | })
403 | .messages({
404 | 'last_name.required': 'Last name is required',
405 | 'last_name.min': 'Last name may not be less than :min characters',
406 | 'last_name.different': 'Last Name must be different than first name',
407 | 'last_name.string': 'Last Name must be a string',
408 | 'first_name.required': 'First name is required',
409 | 'first_name.min': 'First name may not be less than :min characters',
410 | 'first_name.different': 'Last Name must be different than last name',
411 | 'first_name.string': 'First name must be of the string type'
412 | })
413 | .is(name_fields)
414 | );
415 |
416 | multi.steps().add(1,
417 | form({
418 | password: '',
419 | password_confirmation: '',
420 | })
421 | .rules({
422 | password: ['required', 'min:5', 'string', 'confirmed'],
423 | })
424 | .is(password_fields)
425 | );
426 |
427 | multi.steps().add(2,
428 | form({ terms_of_service: '' })
429 | .rules({ terms_of_service: 'accepted|required' })
430 | .messages({
431 | 'terms_of_service.accepted': "Must accept terms of service before moving on",
432 | 'terms_of_service.required': "Must accept terms of service before submitting form",
433 | })
434 | .is(final_step)
435 | );
436 |
437 |
438 | export default {
439 | name: 'multi-step-form',
440 | data: () => ({ multi }),
441 |
442 | methods: {
443 | submit() {
444 | let data = this.multi.steps().list().reduce((data, step) => ({ ...data, ...step.all() }), {});
445 |
446 | console.log('all data: ', form(data).all());
447 | }
448 | }
449 | };
450 | ```
451 |
--------------------------------------------------------------------------------
/bundler/header.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bundler/highlight.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | ## Playground Examples
4 | Curious, but not 100% on whether this is what you're looking for?
5 | Try vuejs-form out for yourself before installing -- here's some live examples ready for you to tinker away at!
6 |
7 | ---
8 | - [Example One (Validate Form On Each User Submit)](https://codepen.io/zhorton34/pen/zYvWZYz)
9 | - [Example One (Validate Form On Each User Update)](https://codepen.io/zhorton34/pen/xxwaYez)
10 | ---
11 |
12 | ## Simple Vue Example
13 |
14 | ---
15 | ```html
16 |
17 |
18 |
19 |
20 | {{ form.errors().get('email') }}
21 |
22 |
23 |
24 |
25 | {{ form.errors().get('password') }}
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | ```
34 | ```js
35 | import form from 'vuejs-form'
36 |
37 | export default {
38 | data: () => ({
39 | form: form({
40 | email: '',
41 | password: '',
42 | password_confirmation: ''
43 | })
44 | .rules({
45 | email: 'email|min:5|required',
46 | password: 'required|min:5|confirmed'
47 | })
48 | .messages({
49 | 'email.email': 'Email field must be an email (durr)',
50 | 'password.confirmed': 'Whoops, :attribute value does not match :confirmed value',
51 | }),
52 | }),
53 |
54 | methods: {
55 | submit() {
56 | if (this.form.validate().errors().any()) return;
57 |
58 | alert('Success, form is validated!');
59 |
60 | console.log('form all(): ', this.form.all());
61 | console.log('form except(): ', this.form.except('password_confirmation'));
62 | },
63 | }
64 | }
65 | ```
66 |
67 | ---
68 |
69 | ## Vue Example Two
70 |
71 | ---
72 |
73 |
74 | ---
75 |
76 | ## Form API
77 |
78 | ---
79 |
80 | - [all](#all)
81 | - [boolean](#boolean)
82 | - [empty](#empty)
83 | - [except](#except)
84 | - [fill](#fill)
85 | - [filled](#filled)
86 | - [forget](#forget)
87 | - [has](#has)
88 | - [hasAny](#hasany)
89 | - [input](#input)
90 | - [keys](#keys)
91 | - [make](#make)
92 | - [missing](#missing)
93 | - [only](#only)
94 | - [set](#set)
95 | - [toArray](#toarray)
96 | - [wrap](#wrap)
97 | - **Extending Form Api**
98 | - [macro](#macros)
99 | - [localMacro](#macros)
100 | - [forceMacro](#macros)
101 | - [forceLocalMacro](#macros)
102 |
103 | ---
104 |
105 | ## Error Messages Api
106 |
107 | ---
108 |
109 | - [form.errors().any()](#any-errors)
110 | - [form.errors().all()](#all-errors)
111 | - [form.errors().list()](#list-errors)
112 | - [form.errors().set(errors)](#set-errors)
113 | - [form.errors().forget()](#forget-errors)
114 | - [form.errors().has(field)](#has-error)
115 | - [form.errors().get(field)](#get-error)
116 | - [form.errors().list(field)](#list-error)
117 | - [form.errors().add(field, message)](#add-error)
118 | - [form.errors().set(field, messages)](#set-field-errors)
119 | - [form.errors().forget(field)](#forget-field)
120 | - [form.errors().getValidator()](#get-errors-validator)
121 | - **Extending Errors Api**
122 | - [form.errors().macro(name, fn)](#macros)
123 | - [form.errors().forceMacro(name, fn)](#macros)
124 | - [form.errors().localMacro(name, fn)](#macros)
125 | - [form.errors().forceLocalMacro(name, fn)](#macros)
126 |
127 |
128 | ---
129 |
130 | ## Validator Api
131 |
132 | ---
133 |
134 | - [form.rules({...})](#form-register-rules)
135 | - [form.messages({...})](#form-customize-error-messages)
136 | - [form.hasValidator()](#form-has-validator)
137 | - [form.setValidator({...})](#form-set-rules)
138 | - [form.validator()](#form-validator-instance)
139 | - [form.validate()](#validate-form-data)
140 | - **Validator Hooks (Documentation Stored in Vuejs Validators Repository)**
141 | - [form.validator().before(callbackHook) (see vuejs-validators repo)](https://github.com/zhorton34/vuejs-validators)
142 | - [form.validator().after(callbackHook) (see vuejs-validators repo)](https://github.com/zhorton34/vuejs-validators)
143 | - [form.validator().passed(callbackHook) (see vuejs-validators repo)](https://github.com/zhorton34/vuejs-validators)
144 | - [form.validator().failed(callbackHook) (see vuejs-validators repo)](https://github.com/zhorton34/vuejs-validators)
145 | - [form.validator().validateWithoutHooks() (see vuejs-validators repo)](https://github.com/zhorton34/vuejs-validators)
146 | - **Extend Validator Api**
147 | - [form.validator().macro(name, fn)](#macros)
148 | - [form.validator().forceMacro(name, fn)](#macros)
149 | - [form.validator().localMacro(name, fn)](#macros)
150 | - [form.validator().forceLocalMacro(name, fn)](#macros)
151 |
152 | ---
153 |
154 | ## Rules Api
155 |
156 | ---
157 | - [accepted](#accepted-rule)
158 | - [alpha](#alpha-rule)
159 | - [alpha_dash](#alpha_dash-rule)
160 | - [alpha_num](#alpha_num-rule)
161 | - [array](#array-rule)
162 | - [between](#between-rule)
163 | - [boolean](#boolean-rule)
164 | - [confirmed](#confirmed-rule)
165 | - [date](#date-rule)
166 | - [date_equals](#date-equals-rule)
167 | - [before (date)](#before-rule)
168 | - [before_or_equal (date)](#before-or-equal-rule)
169 | - [after (date)](#after-rule)
170 | - [after_or_equal (date)](#after-or-equal-rule)
171 | - [greater_than (numeric)](#greater-than-rule)
172 | - [gte (Greater than or equal numeric)](#gte-rule)
173 | - [less_than (numeric)](#less-then-rule)
174 | - [lte (Less than or equal numeric)](#lte-rule)
175 | - [different](#different-rule)
176 | - [digits](#digits-rule)
177 | - [digits_between](#digits_between-rule)
178 | - [distinct](#distinct-rule)
179 | - [email](#email-rule)
180 | - [ends_with](#ends_with-rule)
181 | - [integer](#integer-rule)
182 | - [ip](#ip-rule)
183 | - [ipv4](#ipv4-rule)
184 | - [ipv6](#ipv6-rule)
185 | - [json](#json-rule)
186 | - [max](#max-rule)
187 | - [min](#min-rule)
188 | - [not_regex](#not_regex-rule)
189 | - [not_within](#not_within-rule)
190 | - [number](#number-rule)
191 | - [numeric](#numeric-rule)
192 | - [phone](#phone-rule)
193 | - [regex](#regex-rule)
194 | - [required](#required-rule)
195 | - [same](#same-rule)
196 | - [starts_with](#starts_with-rule)
197 | - [string](#string-rule)
198 | - [url](#url-rule)
199 | - [within](#within-rule)
200 |
201 |
202 |
--------------------------------------------------------------------------------
/bundler/installation.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | ##
Installation
4 |
5 |
6 |
7 | ### NPM
8 |
9 | ```bash
10 | npm install --save-dev vuejs-form
11 | ```
12 |
13 | ### Yarn
14 |
15 | ```bash
16 | yarn add vuejs-form --save
17 | ```
18 |
19 | ### CDN
20 |
21 | ```bash
22 |
23 | ```
24 |
25 | ---
26 |
27 | ##
Four Official Apis
28 |
29 | ---
30 |
31 | - [Form Api](#form-api)
32 | - [Rules Api](#rules-api)
33 | - [Validator Api](#validator-api)
34 | - [Error Messages Api](#error-messages-api)
35 |
--------------------------------------------------------------------------------
/bundler/license.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | ## License
4 |
5 | ---
6 |
7 | MIT © [Zachary Horton (Clean Code Studio)](https://www.youtube.com/c/cleancodestudio)
8 | [Clean Code Studio ~ Clean Code Clean Life ~ Simplify](https://cleancode.studio)
--------------------------------------------------------------------------------
/bundler/macros.md:
--------------------------------------------------------------------------------
1 | ## Macros
2 |
3 | - [Overview](#macros-overview)
4 | - [Macros](#extend-apis-via-macros)
5 | - [Local Macros](#extend-instances-via-local-macros)
6 | - [Force Macros](#overwrite-a-given-apis-core-via-force-macros)
7 | - [Force Local Macros](#overwrite-a-given-instances-core-via-force-local-macros)
8 | - [Macro Capable Apis List](#macro-capable-apis-list)
9 |
10 | ### Macros Overview
11 | - Macros Are The Primary Way This Package And All Major Apis Are Extendable
12 | - One of this packages primary goals is to be unbiased, but provide _extreme_ extendability
13 | - Macros, and specifically four types of macros, are the primary way we are able to obtain this goal
14 | - Macros, in concept are extremely simple.
15 | - They simply add functions, extending behavior
16 | - Macros can accept arguments
17 | - Macros have access to `this` within the callback you are registering
18 | - There are four types of macros.
19 | - localMacro(name, fn) - extend instance with custom function (only the specific )
20 | **Simplest Example**
21 | ```
22 | form().hello(); // undefined
23 |
24 | form().macro('hello', function () {
25 | return 'world';
26 | });
27 |
28 | form().hello(); // 'world'
29 | ```
30 |
31 | ### Extend Apis Via Macros
32 | `macro(name, fn)`
33 | - extend api with function
34 | - instance gains functions and constructor prototype gain function
35 | - applied to all new instances
36 | - can not overwrite core functions
37 | - can not overwrite pre-defined macros
38 | - can not be applied on more than a single instance (Technically you can try, it just won't actually do anything the methods already added)
39 |
40 | **Example: macro()**
41 | Simplify the validation process using a "completed" method wrapper
42 |
43 | ```js
44 | form().macro('completed', function () {
45 | this.validate();
46 |
47 | return this.errors().any() === false;
48 | });
49 |
50 | form({ name: '' }).rules({ name: 'required' }).completed(); // false
51 | form({ name: 'samuel' }).rules({ name: 'required' }).completed(); // true
52 | ```
53 |
54 | ### Extend Instances Via LocalMacros
55 | `localMacro(name, fn)`
56 | **Example:** See multi-step form example provided for `forceLocalMacro` example. It provides a powerful example of possible ways to combine local and forceLocal macros.
57 | - extend instance with function
58 | - instance gains function
59 | - NOT applied to all new instances
60 | - can not overwrite core instances
61 | - can not overwrite pre-defined macros
62 | - can be applied on more than a single instance, but not automatically inherited globally
63 | **Example: localMacro**
64 | ```js
65 | ```
66 | ### Overwrite A Given Apis Core Via Force Macros
67 | `forceMacro(name, fn)`
68 | - overwrite core api or existing macros
69 | - instance and constructor prototypes apply function
70 | - applies on all instances
71 | - can overwrite core functions
72 | - can overwrite pre-defined macros
73 | _NOTE: This is a very powerful function, use caution and when overriding core behavior understand things depend on other things under the hood. Only use this type of macro if no other macro solves your needs_
74 |
75 | **Force Macro Example**
76 | > Overwrite Error Message Apis Get Method To Get A Comma List Of Messages Instead Of The First Message
77 | ```js
78 | let example = form({ name: '' }).rules({ name: 'required|min:3' }).validate();
79 |
80 | example.errors().get('name'); // 'Name field is required'
81 |
82 | example.errors().forceMacro('get', function (field) {
83 | if (this.has(field)) {
84 | return this.list(field).join(', ');
85 | }
86 | });
87 |
88 | example.errors().get('name'); // 'Name field is required, Name field must be more than 3 characters'
89 | ```
90 |
91 | ### Overwrite A Given Instances Core Via Force Local Macros
92 | `forceLocalMacro(name, fn)`
93 | - overwrite instances core behavior or existing macros
94 | - instance applies function
95 | - not applied by all instances, only on single instance
96 | - can overwrite core functions
97 | - can overwrite pre-defined macros
98 | _NOTE: Not quite as dangerous as forceMacro (it's only applied on one instance instead of globally across the api), it is still powerful and should be used only if localMacro doesn't solve your needs_
99 |
100 | **Create A Parent Form With Multiple Child Forms**
101 | _Example uses localMacro & forceLocalMacro (Advanced example)_
102 |
103 | ```js
104 |
105 | let MultiStepForm = form();
106 |
107 | MultiStepForm.localMacro('register', function (children = []) {
108 | this.current = 0;
109 | const $parent = this;
110 |
111 | // Set local macros on each one of the child forms
112 | this.children = children.map(child => {
113 | // 1. localMacro: parent() method references parent form will all steps
114 | child.localMacro('parent', () => $parent);
115 |
116 | // 2. forceLocalMacro: override validate() method to add in a step where child validate method populates parent() errors bag
117 | // Below we'll override the parent validate() method using a forceLocalMacro as well to two way bind this setup
118 | child.forceLocalMacro('validate', function () {
119 | const childForm = this;
120 | childForm.validator().validate();
121 |
122 | childForm.parent().errors().set({
123 | ...childForm.parent().errors().all(),
124 | ...childForm.errors().all(),
125 | });
126 |
127 | return this;
128 | })
129 | });
130 |
131 | /** Add helper methods for managing the multi-step form process **/
132 | this.step = () => this.steps(this.current);
133 | this.steps = index => index !== 'undefined' && this.hasStep(index) ? this.children(index) : this.children;
134 | this.hasStep = index => typeof this.children[index] !== 'undefined';
135 |
136 | this.prevStep = () => { this.current = this.current - 1; };
137 | this.stepNumber = () => this.current + 1;
138 | this.stepsCount = () => this.steps().length ;
139 |
140 | this.hasPrevStep = () => this.hasStep(this.current - 1);
141 | this.hasNextStep = () => this.hasStep(this.current + 1);
142 | this.isLastStep = () => this.step() === this.steps(this.stepCount());
143 | this.isFirstStep = () => this.step() === this.steps(0);
144 |
145 | this.completedStepsCount = () => this.stepNumber();
146 | this.remainingStepsCount = () => this.stepsCount() - this.stepNumber();
147 | this.percentageCompleted = () => (this.completedStepsCount() / 100) * this.stepsCount();
148 | this.percentageRemaining = () => (this.remainingStepsCount() / 100) * this.stepsCount();
149 | this.next = () => {
150 | if (this.hasNextStep()) this.current = this.current + 1;
151 | };
152 | this.prev = () => {
153 | if (this.hasPrevStep()) this.current = this.current - 1;
154 | };
155 | this.to = index => {
156 | if (this.hasStep(index)) this.current = index;
157 | }
158 |
159 | return this;
160 | });
161 |
162 | /** forceLocalMacro to overwrite default all method on MultiStepForm ~ aggregating all child form data **/
163 | MultiStepForm.forceLocalMacro('all', function () {
164 | return this.children.reduce((data, child) => ({
165 | ...data,
166 | ...child
167 | }),
168 | {});
169 | });
170 |
171 | /** forceLocalMacro to overwrite default validate method on MultiStepForm ~ setting all error messages **/
172 | MultiStepForm.forceLocalMacro('validate', function () {
173 | this.errors().set(
174 | this.children.reduce((errors, child) => ({
175 | ...errors,
176 | ...child.validate().errors().all()
177 | }),
178 | {})
179 | );
180 |
181 | return this;
182 | });
183 |
184 | MultiStepForm.register([
185 | form({ first_name: '', last_name: '' }).rules({ first_name: 'required', last_name: 'required' }),
186 | form({ email: '', phone_number: '' }).rules({ email: 'required|email', phone: 'required|phone' }),
187 | form({ password: null, password_confirmation: '' }).rules({ password: 'required|min:7|confirmed|string '}),
188 | form({ terms_of_services: null }).rules({ terms_of_services: 'required|accepted' })
189 | ]);
190 |
191 | MultiStepForm.validate().errors().list();
192 | ```
193 |
194 | ```
195 | Output:
196 | [
197 | 'First name is a required field',
198 | 'Last name is a required field',
199 | 'Email is a required field',
200 | 'Email must be an email',
201 | 'Phone number is a required field',
202 | 'Phone number must be a valid phone number',
203 | 'Password is a required field',
204 | 'Password must be at least 7 characters',
205 | 'Password must have the same value as the password confirmation field',
206 | 'Password must be a string',
207 | 'Terms Of Service is a required field',
208 | 'Terms Of Service has not been accepted, please accept to continue',
209 | ]
210 | ```
211 | ### Macro Capable Api List
212 | - [Form Api Macros](#form-api-macros)
213 | - [Validator Api Macros](#validator-api-macros)
214 | - [Error Message Api Macros](#error-message-api-macros)
215 |
216 | #### Form Api Macros
217 | - form().macro(name, fn)
218 | - form().localMacro(name, fn)
219 | - form().forceMacro(name, fn)
220 | - form().forceLocalMacro(name, fn)
221 |
222 | #### Validator Api Macros
223 | - form().validator().macro(name, fn)
224 | - form().validator().localMacro(name, fn)
225 | - form().validator().forceMacro(name, fn)
226 | - form().validator().forceLocalMacro(name, fn)
227 |
228 | #### Error Message Api Macros
229 | - form().errors().macro(name, fn)
230 | - form().errors().localMacro(name, fn)
231 | - form().errors().forceMacro(name, fn)
232 | - form().errors().forceLocalMacro(name, fn)
233 |
--------------------------------------------------------------------------------
/bundler/markdown.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | const markdown = {
5 | make: (...lines) => {
6 | return [
7 | '\n',
8 | lines.reduce((created, line) => [
9 | ...created,
10 | line(markdown)
11 | ], []).join('\n'),
12 | '\n',
13 | ];
14 | },
15 |
16 | url: (text, url) => `[${text}](${url})`,
17 | link: (text, link) => `[${text}](#${link})`,
18 |
19 | li: text => `- ${text}`,
20 | list: list => list.map(item => `- ${item}`).join('\n'),
21 | ul: {
22 | li: text => `- ${text}`,
23 | url: (text, url) => markdown.url(text, url),
24 | link: (text, link) => markdown.link(text, link),
25 | },
26 |
27 | table: ({ headers, rows }) => {
28 | const make = items => ['|', items, '|'];
29 | return [
30 | make(headers.join('|')),
31 | make(headers.map(header => '---').join('|')),
32 | ...rows.reduce((rows, row) => [ ...rows, make(row.join('|')) ], []),
33 | ]
34 | .map(row => row.join(''))
35 | .join('\n');
36 | },
37 | hr: () => '---',
38 | br: () => `\n`,
39 | h1: text => `# ${text}`,
40 | h2: text => `## ${text}`,
41 | h3: text => `### ${text}`,
42 | h4: text => `#### ${text}`,
43 | h5: text => `##### ${text}`,
44 |
45 | pre: text => '```' + text + '```',
46 | bold: text => `**${text}**`,
47 | italic: text => `_${text}_`,
48 | quote: text => `> ${text}`,
49 |
50 | inline: text => "`" + text + "`",
51 | block: text => "```" + text + "```",
52 | js: text => "```javascript" + text + "```",
53 | py: text => "```python" + text + "```",
54 | bash: text => "```bash" + text + "```",
55 | youtube: ({ id, width = '240', height = '240', border = '10', alt = 'Tutorial', target = "_blank" }) => `
56 |
57 |
58 |
59 | `,
60 | };
61 |
62 | module.exports = markdown;
63 | module.exports.default = markdown;
64 | module.exports.markdown = markdown;
65 |
--------------------------------------------------------------------------------
/bundler/purpose.md:
--------------------------------------------------------------------------------
1 |
2 | ##
That Vue Form
3 |
4 | 
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/bundler/security_vulnerabilities.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | ## Security Vulnerabilities
4 |
5 | ---
6 |
7 | If you discover a security vulnerability within Clean Code Studio Packages Or Specifically within vuejs-form, please
8 | send an e-mail to Zachary Horton via zak@cleancode.studio. All security vulnerabilities will be promptly addressed.
9 |
--------------------------------------------------------------------------------
/bundler/setup.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | ## Setup
4 |
5 | ---
6 |
7 | ### Npm Setup
8 | ```
9 | npm install vuejs-form --save-dev
10 | ```
11 |
12 | ```
13 | import from from 'vuejs-form'; // Or const form = require('vuejs-form');
14 |
15 | let RegisterForm = form({
16 | email: '',
17 | password: '',
18 | password_confirmation: ''
19 | })
20 | .rules({
21 | email: ['required', 'email', 'min:5'],
22 | password: ['min:5', 'required', 'confirmed'],
23 | })
24 | .messages({
25 | 'email.email': 'Email must be an email',
26 | 'email.required': 'Email is a required field',
27 | 'email.min': 'Email is less than :min characters',
28 |
29 | 'password.required': 'Password is required',
30 | 'password.confirmed': 'Password value must match password confirmation value',
31 | 'password.min': 'Password is not secure enough (Must be longer than :min characters)',
32 | })
33 | .validate();
34 | ```
35 |
36 | ### CDN Setup
37 |
38 | ```
39 |
40 |
41 |
62 | ```
63 |
--------------------------------------------------------------------------------
/bundler/utilization.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | ## Utilization
4 |
5 | ---
6 |
7 | ```js
8 | import form from 'vuejs-form'
9 |
10 | const LoginForm = form({
11 | name: '',
12 | email: '',
13 | password: '',
14 | })
15 |
16 | LoginForm.name // ''
17 | LoginForm.name = 'sarah'
18 | LoginForm.name // 'sarah'
19 |
20 | form({
21 | name: '',
22 | email: '',
23 | password: '',
24 | }).all() // { name: 'sarah', email: '', password: '' }
25 | form({
26 | name: '',
27 | email: '',
28 | password: '',
29 | }).has('email', 'password') // true
30 | form({
31 | name: '',
32 | email: '',
33 | password: '',
34 | }).has('email', 'something') // false
35 | form({
36 | name: '',
37 | email: '',
38 | password: '',
39 | }).hasAny('email', 'something') // true
40 | form({
41 | name: '',
42 | email: '',
43 | password: '',
44 | }).empty('email') // true
45 | form({
46 | name: '',
47 | email: '',
48 | password: '',
49 | }).filled('email') // false
50 | form({
51 | name: '',
52 | email: '',
53 | password: '',
54 | }).filled('name') // true
55 | form({
56 | name: '',
57 | email: '',
58 | password: '',
59 | }).boolean('email') // false
60 | form({
61 | name: '',
62 | email: '',
63 | password: '',
64 | }).only('email', 'name') // { email: '', name: '', }
65 | form({
66 | name: '',
67 | email: '',
68 | password: '',
69 | }).except('password') // { email: '', name: '' }
70 | form({
71 | name: '',
72 | email: '',
73 | password: '',
74 | }).input('password') // ''
75 | form({
76 | name: '',
77 | email: '',
78 | password: '',
79 | }).input('email', 'example@gmail.com') // 'example@gmail.com'
80 |
81 | LoginForm.fill({
82 | name: 'tim',
83 | email: 'tim@gmail.com',
84 | password: 'secret'
85 | })
86 |
87 | LoginForm.all() // { name: 'sarah', email: 'tim@gmail.com', password: 'secret' }
88 |
89 | LoginForm.set({
90 | name: 'jamie',
91 | email: 'jamie@gmail.com',
92 | password: 'password'
93 | })
94 |
95 | LoginForm.all() // { name: 'jamie', email: 'tim@gmail.com', password: 'secret' }
96 |
97 | LoginForm.keys() // ['name', 'email', 'password']
98 |
99 | LoginForm.missing('verified') // true
100 | LoginForm.missing('email') // false
101 |
102 | LoginForm.toArray()
103 | /**
104 | [
105 | { key: 'name', value: 'jamie' },
106 | { key: 'email', value: 'tim@gmail.com' },
107 | { key: 'password', value: 'secret' }
108 | ]
109 | */
110 |
111 | LoginForm.wrap('data')
112 | /**
113 | {
114 | data: {
115 | name: 'jamie',
116 | email: 'tim@gmail.com',
117 | password: 'secret'
118 | }
119 | }
120 | */
121 |
122 | LoginForm.forget('password', 'email')
123 | LoginForm.all() // { name: 'jamie' }
124 |
125 | /**
126 | * When dealing with HTML elements like checkboxes, your application may receive "truthy" values that are actually strings. For example, "true" or "on". For convenience, you may use the boolean method to retrieve these values as booleans. The boolean method returns true for 1, "1", true, "true", "on", and "yes". All other values will return false:
127 | * Boolean checks for
128 | */
129 | LoginForm.boolean('name') // false
130 |
131 |
132 | LoginForm.terms = true
133 | LoginForm.boolean('terms') // true
134 | LoginForm.terms = 'true'
135 | LoginForm.boolean('terms') // true
136 | LoginForm.terms = 'yes'
137 | LoginForm.boolean('terms') // true
138 | LoginForm.terms = 'on'
139 | LoginForm.boolean('terms') // true
140 | LoginForm.terms = "1"
141 | LoginForm.boolean('terms') // true
142 | LoginForm.terms = 1
143 | LoginForm.boolean('terms') // true
144 |
145 | /** Anything else will return false Ex: */
146 | LoginForm.terms = 'asdfsdf'
147 | LoginForm.boolean('terms') // false
148 | ```
149 |
150 | #### Extend Form Functionality
151 | ```js
152 | import form from 'vuejs-form'
153 |
154 | form().macro('count', () => {
155 | return this.keys().length
156 | })
157 |
158 | form().macro('mapInto', into => {
159 | // NOTICE: this.data is where the input object is actually stored
160 |
161 | this.data = Object.entries(this.data).reduce((input, [key, value]) => ({
162 | ...input,
163 | ...into(key, value)
164 | }),
165 | {});
166 |
167 | return this
168 | })
169 |
170 |
171 |
172 | const extendedForm = form({
173 | email: 'example@gmail',
174 | password: 'secret',
175 | })
176 |
177 | form().macro((key, value) => ({ [key]: value.split('@') })).all()
178 | /**
179 | * { email: ['example', 'gmail'], password: 'secret' }
180 | */
181 | ```
182 |
183 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/bundler/validator.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | ## Validator Api
4 |
5 | ---
6 |
7 | - [form.rules({...})](#form-register-rules)
8 | - [form.messages({...})](#form-customize-error-messages)
9 | - [form.validator(...)](#form-validator-instance)
10 | - [form.validate(...)](#validate-form-data)
11 | - [form.hasValidator()](#form-has-validator)
12 | - [form.setValidator({...})](#form-set-rules)
13 |
14 | ### Form Register Rules
15 | > [@SeeAvailableValidationRules](#rules-api)
16 | ```js
17 | form(data).rules({
18 | name: 'required|min:4',
19 | link: 'required|url',
20 | category: 'required|within:blue,reg,green'
21 | });
22 | ```
23 |
24 | >
25 | > Optionally Use Arrays Syntax Instead Of Pipes
26 | >
27 |
28 | ```js
29 | form(data).rules({
30 | name: ['required', 'min:4'],
31 | link: ['required', 'url'],
32 | category: ['required', 'within:blue,reg,green']
33 | });
34 | ```
35 |
36 | ### Form Customize Error Messages
37 | - All rules have global default error messages shown when rule fails validation.
38 | - Optionally, you are able to override the global defaults rule messages
39 | - Simply use the form(data).rules(set)`.messages({ '{field}.{rule}': 'custom message for failing rule on field' });`
40 | ```js
41 | let data = { email: ['required', 'email'] }
42 | form({ email: 'chad'}).rules({
43 | email: ['required', 'email']
44 | })
45 | .messages({
46 | 'email.required': 'Email field is called email, needa make it an email (Hence Email Field Name, dont worry ~ we added validation just in case you forgot to make the email field an email)'
47 | })
48 | ```
49 | ### Form Validator Instance
50 | - Get [Validator Instance](https://github.com/zhorton34/vuejs-validators.js)
51 | ```js
52 | form(data).rules(options).messages(customMessages);
53 |
54 | // form.validator().addMessage(field, error)
55 | // form.validator().addRule(field, rules)
56 | // etc...
57 | ```
58 |
59 | ### Validate Form Data
60 | - Check current form data against associated form rules
61 | - IMPORTANT: form MUST call validate() method before retrieving current errors
62 |
63 | _COMMON GOTCHA!!!!_
64 | - This wont get the current form errors
65 | - The `form.validate()` method was Never called
66 | ```js
67 | let data = { name: '' };
68 | let rules = { name: 'required' };
69 |
70 | form(data).rules(rules).errors().list();
71 |
72 | // --------------------------------------------
73 | // Form SHOULD fail, but errors list is empty
74 | // --------------------------------------------
75 | // Output: []
76 | // --------------------------------------------
77 | ```
78 |
79 | > _What's the reason?_
80 | >
81 | > Retrieving errors before validating form data
82 | >
83 | > would retrieve our error messages Api instance,
84 | > but it hasn't been filled with our forms error messages.
85 | >
86 | > form.validate() compares form data against form rules, populating our form errors with failing rule messages.
87 | >
88 |
89 | **Validate THEN resolve the errors (Using forms fluent api)**
90 | ```js
91 | let data = { name: '' };
92 | let rules = { name: 'required' };
93 |
94 | form(data).rules(rules).validate().errors().list();
95 | // Output: ['Name field is required']
96 |
97 | // Again, we'll need to validate before retrieving our
98 | // errors to validate that the values passes our given rules
99 | form.name = 'hello world';
100 |
101 | form.errors().list();
102 | // Output: ['Name field is required']
103 |
104 | form.validate().errors().list();
105 | // Output: [];
106 | ```
107 | >
108 | >
109 | > Fluently call validate() before calling errors() is simple and to the point.
110 | >
111 | > At first, this may seem like a tedious extra step. Many may wonder why we don't simply auto-validate the data?
112 |
113 | Reason for `form.validate().errors()` Instead of simply `form.errors()` triggering the validation.
114 | - Reactive frameworks may use `errors()` and the associated Error Messages Api ([@See Form Error Messages Api](#form-error-messages-api))
115 | - Without providing the option for the end developer to determine when the form validates
116 | - Async requests, only validate once we've resolved some given data
117 | - Immediate display of errors (Not always wanted)
118 | - Option Open To Immediately show error messages ([@See Vue Watcher Example](#vue-example-two))
119 | - Some other developers may only want to validate data on form submission
120 | - Many validation rules can be abstracted using the form Api to simply disable the ability to submit a button
121 | - EX: ``
122 | - Then within `submit() method` simply run `if (this.form.validate().errors().any()) return;`
123 | - That allows the option to set up vuejs-form more like a traditional Form, and avoid many complexities that come along with maintaining the status of our reactive state
124 | - etc...
125 |
126 | ### Form Has Validator
127 | Determine if form has a validator instance attached to it
128 | ```js
129 | form.hasValidator(); // true or false
130 | ```
131 |
132 | ### Form Set Validator
133 | - Set Validator Instance
134 | - Optionally import the validator instance itself, and extend
135 | its functionality validator().macro(add_method, method).
136 | - Then use form macros to track the current step form.macro(add_method, method).
137 | - vuejs-validators.js Also has validator life cycle hooks documented that are available here, but only documented within vuejs-form.js. Very helpful for multi-step forms
138 |
139 | ```js
140 | const { form, validator } = require('vuejs-form');
141 |
142 |
143 | form().macro('setSwitchableValidators', (first, second) => {
144 | this.toggleValidators =
145 | this.toggleBetween = first
146 | });
147 |
148 | ```
149 | ## Rules Api
150 | - [accepted](#accepted-rule)
151 | - [date](#date-rule)
152 | - [date_equals](#date-equals-rule)
153 | - [before (date)](#before-rule)
154 | - [before_or_equal (date)](#before-or-equal-rule)
155 | - [after (date)](#after-rule)
156 | - [after_or_equal (date)](#after-or-equal-rule)
157 | - [greater_than (numeric)](#greater-than-rule)
158 | - [gte (Greater than or equal numeric)](#gte-rule)
159 | - [less_than (numeric)](#less-then-rule)
160 | - [lte (Less than or equal numeric)](#lte-rule)
161 | - [alpha](#alpha-rule)
162 | - [alpha_dash](#alpha_dash-rule)
163 | - [alpha_num](#alpha_num-rule)
164 | - [array](#array-rule)
165 | - [between](#between-rule)
166 | - [boolean](#boolean-rule)
167 | - [confirmed](#confirmed-rule)
168 | - [different](#different-rule)
169 | - [digits](#digits-rule)
170 | - [digits_between](#digits_between-rule)
171 | - [distinct](#distinct-rule)
172 | - [email](#email-rule)
173 | - [ends_with](#ends_with-rule)
174 | - [integer](#integer-rule)
175 | - [ip](#ip-rule)
176 | - [ipv4](#ipv4-rule)
177 | - [ipv6](#ipv6-rule)
178 | - [json](#json-rule)
179 | - [max](#max-rule)
180 | - [min](#min-rule)
181 | - [not_regex](#not_regex-rule)
182 | - [not_within](#not_within-rule)
183 | - [number](#number-rule)
184 | - [numeric](#numeric-rule)
185 | - [phone](#phone-rule)
186 | - [regex](#regex-rule)
187 | - [required](#required-rule)
188 | - [same](#same-rule)
189 | - [starts_with](#starts_with-rule)
190 | - [string](#string-rule)
191 | - [url](#url-rule)
192 | - [within](#within-rule)
193 |
194 |
195 |
196 | ### Date Equals Rule
197 | (Date)
198 | The field under validation must be the same date as the rules date
199 |
200 | > Passes Date Equals Rule
201 | ```js
202 | let form = {
203 | one: '4-22-1997',
204 | two: 'April 22 2025'
205 | }
206 |
207 | let rules = {
208 | one: 'date_equals:4-22-1997',
209 | two: 'date_equals:April 22 2025',
210 | }
211 | ```
212 |
213 | > Fails Date Equals Rule
214 | ```js
215 | let form = {
216 | one: '4-22-1997',
217 | two: '2-12-1997'
218 | }
219 |
220 | let rules = {
221 | one: 'date_equals:4-24-1998',
222 | two: 'date_equals:1-11-1996',
223 | }
224 | ```
225 |
226 | ### Before Rule
227 | (Date)
228 |
229 | The Field under evaluation must be before the compared date
230 |
231 | > Passes Before (Date) Rule
232 | ```
233 | let form = {
234 | one: '4-22-1997',
235 | two: '2-12-1997'
236 | }
237 |
238 | let rules = {
239 | one: 'before:4-22-1998',
240 | two: 'before:2-12-1997',
241 | }
242 | ```
243 |
244 | > Fails Before (Date) Rule
245 | ```js
246 | let form = {
247 | one: '4-22-1997',
248 | two: '3-12-1997'
249 | }
250 |
251 | let rules = {
252 | one: 'before:4-22-1997',
253 | two: 'before:2-3-1996',
254 | }
255 | ```
256 |
257 | ### Before Or Equal Rule
258 | (Date)
259 | The field under validation must be before or equal to the compared date.
260 |
261 | > Passes Before Or Equal (Date) Rule
262 | ```js
263 | let form = {
264 | one: '4-22-1997',
265 | two: '2-12-1997'
266 | }
267 |
268 | let rules = {
269 | one: 'before_or_equal:3-21-1998',
270 | two: 'before_or_equal:2-12-1997',
271 | }
272 | ```
273 |
274 | > Fails Before Or Equal (Date) Rule
275 | ```js
276 | let form = {
277 | one: '4-22-1997',
278 | two: '2-3-1997'
279 | }
280 |
281 | let rules = {
282 | one: 'before_or_equal:4-23-1997',
283 | two: 'before_or_equal:2-3-1996',
284 | }
285 | ```
286 |
287 | ### After Rule
288 | (Date)
289 |
290 | The Field under evaluation must be after the compared date
291 |
292 | > Passes After (Date) Rule
293 | ```js
294 | let form = {
295 | one: '4-22-1997',
296 | two: '2-2-1997'
297 | }
298 |
299 | let rules = {
300 | one: 'after:4-23-1997',
301 | two: 'after:2-3-1996',
302 | }
303 | ```
304 |
305 | ### Date Rule
306 | (Date)
307 | The field under validation must be a valid, non-relative date according to the new Date js constructor.
308 |
309 | > Passes Date Rule
310 | - 4.22.1997
311 | - 4-22-1997
312 | - 4/22/1997
313 | - April 22 1997
314 | - Tuesday April 22 1997
315 |
316 | > Fails Date Rule
317 | - asdfweadf
318 | - 23423423
319 | - []
320 |
321 | > Fails After (Date) Rule
322 | ```js
323 | let form = {
324 | one: '4-22-1997',
325 | two: '2-12-1997'
326 | }
327 |
328 | let rules = {
329 | one: 'after:4-22-1998',
330 | two: 'after:1-11-1996',
331 | }
332 | ```
333 |
334 |
335 | ### After Or Equal Rule
336 | (Date)
337 | The field under validation must be after or equal to the compared date.
338 |
339 | > Passes After Or Equal (Date) Rule
340 | ```js
341 | let form = {
342 | one: '4-22-1997',
343 | two: '1-11-2013',
344 | }
345 |
346 | let rules = {
347 | one: 'after_or_equal:4-22-1997',
348 | two: 'after_or_equal:2-12-2014',
349 | }
350 | ```
351 |
352 | > Fails After Or Equal (Date) Rule
353 | ```js
354 | let form = {
355 | one: '4-22-1997',
356 | two: '2-12-1997'
357 | }
358 |
359 | let rules = {
360 | one: 'after_or_equal:4-23-1997',
361 | two: 'after_or_equal:2-3-1996',
362 | }
363 | ```
364 |
365 |
366 | ### Accepted Rule
367 |
368 | The field under form must be yes, on, 1, or true. This is useful for validating "Terms of Service" acceptance.
369 |
370 | > Passing Accepted Rule
371 | ```js
372 | let data = { terms_of_service: 'no' };
373 | let rules = { terms_of_service: 'accepted' };
374 |
375 | // false
376 | form(data).rules(rules).validate().errors().has('terms_of_service');
377 | ```
378 |
379 | > Failing Accepted Rule
380 | ```js
381 | let data = { terms_of_service: null }
382 | let rules = { terms_of_service: 'accepted' }
383 |
384 | // true
385 | form(data).rules(rules).validate().errors().has('terms_of_services');
386 | ```
387 |
388 |
389 | ### Alpha Rule
390 | The field under form must be entirely alphabetic characters.
391 |
392 | > Passing Alpha Rule
393 | ```js
394 | let data = { letters: 'asdeddadfjkkdjfasdf' };
395 | let rules = { letters: ['alpha'] };
396 |
397 | // false
398 | form(data).rules(rules).validate().errors().has('letters');
399 | ```
400 |
401 | > Failing Alpha Rule
402 | ```js
403 | let data = { letters: '5-@'}
404 | let rules = { letters: ['alpha'] }
405 |
406 | // true
407 | form(data).rules(rules).validate().errors().has('letters');
408 | ```
409 |
410 | ### Alpha Dash Rule
411 | The field under form may have alpha-numeric characters, as well as dashes and underscores.
412 |
413 | > Passing Alpha Dash Rule
414 |
415 | ```js
416 | let data = { slug: 'user_name' };
417 | let rules = { slug: ['alpha_dash'] };
418 |
419 | // false
420 | form(data).rules(rules).validate().errors().has('slug');
421 | ```
422 |
423 | > Failing Alpha Dash Rule
424 | ```js
425 | let data = { words: 'hello world'}
426 | let rules = { words: ['alpha_dash'] }
427 |
428 | // true
429 | form(data).rules(rules).validate().errors().has('words');
430 | ```
431 |
432 | ### Alpha Num Rule
433 | The field under form must be entirely alpha-numeric characters.
434 |
435 | > Passing Alpha Num Rule
436 |
437 | ```js
438 | let data = { key: '4asdasdfe4d23545w634adf' };
439 | let rules = { key: ['alpha_num'] };
440 |
441 | // false
442 | form(data).rules(rules).validate().errors().any();
443 | ```
444 |
445 | > Failing Alpha Num Rule
446 | ```js
447 | let data = { identifier: '1-asdf4adf_d_42'}
448 | let rules = { identifier: ['alpha_num'] }
449 |
450 | // true
451 | form(data).rules(rules).validate().errors().any();
452 | ```
453 |
454 | ### Array Rule
455 | The field under form must be a JS array.
456 |
457 | > Passing Array Rule
458 | ```js
459 | let data = { list: ['banana', 'broccoli', 'carrot'] };
460 | let rules = { list: 'array' };
461 |
462 | // false
463 | form(data).rules(rules).validate().errors().any();
464 | ```
465 |
466 | > Failing Array Rule
467 | ```js
468 | let data = { options: { name: 'hey world' } }
469 | let rules = { options: 'array' }
470 |
471 | // true
472 | form(data).rules(rules).validate().errors().any();
473 | ```
474 |
475 |
476 | ### Email Rule
477 | The given field value must be an email
478 |
479 | > Passing Email Rule
480 | ```js
481 | let data = { email: 'example@cleancode.studio' };
482 | let rules = { email: ['email'] };
483 |
484 | // false
485 | form(data).rules(rules).validate().errors().any();
486 | ```
487 |
488 | > Failing Email Rule
489 | ```js
490 | let data = { email: 'asdfsdaf@.net'}
491 | let rules = { email: ['email'] }
492 |
493 | // true
494 | form(data).rules(rules).validate().errors().any();
495 | ```
496 |
497 |
498 | ### Boolean Rule
499 | - Boolish form, not strict boolean check
500 | - Validates that field value is "truthy" or "falsy"
501 |
502 | |**Truthy**|**Falsy**|
503 | |---|---|
504 | |1|0|
505 | |"1"|"0"|
506 | |"on"|"off"|
507 | |"On"|"No"|
508 | |"ON"|"OFF"|
509 | |"yes"|"no"|
510 | |"Yes"|"Off"|
511 | |"YES"|"NO"|
512 | |true|false|
513 | |"true"|"false"|
514 | |"True"|"False"|
515 | |"TRUE"|"FALSE"|
516 |
517 | > Passing Boolean Rule
518 | ```js
519 | let data = { selected: 'Yes' };
520 | let rules = { selected: ['boolean'] };
521 |
522 | // false
523 | form(data).rules(rules).validate().errors().any();
524 | ```
525 |
526 | > Failing Boolean Rule
527 | ```js
528 | form = { selected: null };
529 | rules = { selected: ['boolean'] };
530 |
531 | // true
532 | form(data).rules(rules).validate().errors().any();
533 | ```
534 |
535 |
536 | ### Confirmed form Rule
537 | - `{field}` value must match `{field}_confirmation` value
538 | - Example `password` must match `password_confirmation` value to pass `confirmed` ruled
539 | > Passing Confirmed Rule
540 | ```js bash
541 | let data = { password: 'secret', password_confirmation: 'secret' }
542 | let rules = { password: 'confirmed' }
543 |
544 | // false
545 | form(data).rules(rules).validate().errors().any();
546 | ```
547 |
548 | > Failing Confirmed Rule
549 | ```js bash
550 | let data = { password: 'secret' };
551 | let rules = { password: 'confirmed' };
552 |
553 | // true
554 | form(data).rules(rules).validate().errors().any();
555 | form.password_confirmation = 'something_something';
556 |
557 | // true
558 | form.validate().errors().any();
559 | ```
560 |
561 | > Passing Confirmed Rule Again
562 | ```js bash
563 | form.password_confirmation = 'secret';
564 |
565 | // false
566 | form.validate().errors().any();
567 | ```
568 |
569 | ### Greater Than Rule
570 | (Numeric)
571 |
572 | Number must be greater than compared value
573 |
574 | > Passing greater than rule
575 | ```js
576 |
577 | let form = {
578 | age: 24,
579 | members: 19,
580 | percentage: 0.4,
581 | };
582 |
583 | let rules = {
584 | age: 'greater_than:13',
585 | members: 'greater_than:10',
586 | percentage: 'greater_than:0.35',
587 | };
588 | ```
589 |
590 | > Failing greater than rule
591 | ```js
592 | let form = {
593 | age: 24,
594 | members: 19,
595 | percentage: 0.4,
596 | };
597 |
598 | let rules = {
599 | age: 'greater_than:24',
600 | members: 'greater_than:100',
601 | percentage: 'greater_than:0.9',
602 | };
603 | ```
604 |
605 | ### Gte Rule
606 | (Greater Than Or Equal - Numeric)
607 | Number must be greater than or equal to compared value
608 |
609 | > Passing greater than or equal rule (gte)
610 | ```js
611 |
612 | let form = {
613 | age: 24,
614 | members: 19,
615 | percentage: 0.4,
616 | };
617 |
618 | let rules = {
619 | age: 'gte:24',
620 | members: 'gte:10',
621 | percentage: 'gte:0.35',
622 | };
623 | ```
624 |
625 | > Failing greater than or equal rule (gte)
626 | ```js
627 |
628 | let form = {
629 | age: 24,
630 | members: 19,
631 | percentage: 0.4,
632 | };
633 |
634 | let rules = {
635 | age: 'greater_than:25',
636 | members: 'greater_than:100',
637 | percentage: 'greater_than:0.9',
638 | };
639 | ```
640 |
641 | ### Less Than Rule
642 | (Numeric)
643 |
644 | Number must be less than compared value
645 |
646 | > Passing less than rule
647 | ```js
648 |
649 | let form = {
650 | age: 24,
651 | members: 19,
652 | percentage: 0.4,
653 | } ;
654 |
655 | let rules = {
656 | age: 'less_than:25',
657 | members: 'less_than:20',
658 | percentage: 'less_than:0.8',
659 | }
660 | ```
661 |
662 | > Failing less than rule
663 | ```js
664 | let form = {
665 | age: 24,
666 | members: 19,
667 | percentage: 0.4,
668 | };
669 |
670 | let rules = {
671 | age: 'less_than:24',
672 | members: 'less_than:10',
673 | percentage: 'less_than:0.1',
674 | }
675 | ```
676 |
677 |
678 | ### Lte Rule
679 | (Less than or equal - Numeric)
680 |
681 | Number must be less than or equal to compared value
682 |
683 | > Passing Less than or equal (lte) rule
684 | ```js
685 |
686 | let form = {
687 | age: 24,
688 | members: 19,
689 | percentage: 0.4,
690 | } ;
691 |
692 | let rules = {
693 | age: 'lte:24',
694 | members: 'lte:20',
695 | percentage: 'lte:0.8',
696 | }
697 | ```
698 |
699 | > Failing less than or equal (lte) rule
700 | ```js
701 | let form = {
702 | age: 24,
703 | members: 19,
704 | percentage: 0.4,
705 | };
706 |
707 | let rules = {
708 | age: 'less_than:24',
709 | members: 'less_than:10',
710 | percentage: 'less_than:0.5',
711 | }
712 | ```
713 |
714 | ### Different form Rule
715 | The given field value is different than another field value
716 |
717 | > Passing Different Rule
718 | ```js bash
719 | let data = { password: 'asdfasdfasdf', confirm_password: 'secret' };
720 | let rules = { password: 'different:confirm_password' };
721 |
722 | form(data).rules(rules).validate().errors().any();
723 | ```
724 |
725 | > Failing Different Rule
726 | ```js bash
727 | let data = { password: 'secret', confirm_password: 'secret' }
728 | let rules = { password: 'different:confirm_password' }
729 |
730 | form(data).rules(rules).validate().errors().any();
731 | ```
732 |
733 |
734 | ### Digits Rule
735 | The field under form must be numeric and must have an exact length of value.
736 |
737 | > Passing Digits Rule
738 | ```js
739 | let data = { amount: '10000' }
740 | let rules = { amount: 'digits:6' }
741 |
742 | form(data).rules(rules).validate().errors().any();
743 | ```
744 |
745 | > Failing Digits Rule
746 | ```js
747 | let data = { amount: '10000' }
748 | let rules = { amount: 'digits:4' }
749 |
750 | form(data).rules(rules).validate().errors().any();
751 | ```
752 |
753 | ### Digits Between Rule
754 | The field under form must be numeric and have a length between the lower and upper limit defined.
755 |
756 | > Passing Digits Between Rule
757 | ```js
758 | let data = { amount: '10000' }
759 | let rules = { amount: 'digits_between:4,6' }
760 |
761 | form(data).rules(rules).validate().errors().any();
762 | ```
763 |
764 | > Failing Digits Between Rule
765 | ```js
766 | let data = { amount: '10000' }
767 | let rules = { amount: 'digits_between:3,5' }
768 |
769 | form(data).rules(rules).validate().errors().any();
770 | ```
771 |
772 | ### Distinct Rule
773 | The field under form must be an array with no duplicate values.
774 |
775 | > Passing Distinct Rule
776 | ```js
777 | let data = { shopping_list: ['ham', 'eggs', 'milk', 'turkey'] }
778 | let rules = { shopping_list: 'distinct' }
779 |
780 | form(data).rules(rules).validate().errors().any();
781 | ```
782 |
783 | > Failing Distinct Rule
784 | ```js
785 |
786 | let data = { shopping_list: ['ham', 'ham', 'eggs', 'milk', 'turkey'] }
787 | let rules = { shopping_list: 'distinct' }
788 |
789 | form(data).rules(rules).validate().errors().any();
790 | ```
791 |
792 | ### Email Rule
793 | The given field value must be an email
794 |
795 | > Passing Email Rule
796 | ```js
797 | let data = { email: 'example@cleancode.studio' };
798 | let rules = { email: ['email'] };
799 |
800 | form(data).rules(rules).validate().errors().any();
801 | ```
802 |
803 | > Failing Email Rule
804 | ```js
805 | let data = { email: 'asdfsdaf@.net'}
806 | let rules = { email: ['email'] }
807 |
808 | form(data).rules(rules).validate().errors().any();
809 | ```
810 |
811 | ### Ends With Rule
812 | The field under form must end with one of the given values.
813 |
814 | > Passing Ends With Rule
815 | ```js
816 | let data = { name: 'sammie' };
817 | let rules = { name: 'ends_with:sl,ie,asx' };
818 |
819 | form(data).rules(rules).validate().errors().any();
820 | ```
821 |
822 | > Failing Ends With Rule
823 | ```js
824 | let data = { name: 5 };
825 | let rules = { name: 'ends_with:sl,ie,asx' };
826 |
827 | form(data).rules(rules).validate().errors().any();
828 |
829 | form.setData({ name: 'azure' }).setRules({ name: 'ends_with:sl,ie,asx' })
830 |
831 | form.validate().errors().any();
832 | ```
833 |
834 |
835 | ### Integer Rule
836 | This form rule does not verify that the input is of the "integer" variable type, only that the input is a string or numeric value that contains an integer.
837 |
838 | > Passing Integer Rule
839 | ```js
840 | let data = { students: 25 }
841 | let rules = { students: ['integer'] }
842 |
843 | form(data).rules(rules).validate().errors().any();
844 | ```
845 |
846 | > Failing Integer Rule
847 | ```js
848 | let data = { students: 'yes' }
849 | let rules = { students: ['integer'] }
850 |
851 | form(data).rules(rules).validate().errors().any();
852 | ```
853 |
854 | ### IP Rule
855 | This form rule confirms that value is an IP address.
856 |
857 | > Passing IP Rule
858 | - "115.42.150.37"
859 | - "192.168.0.1"
860 | - "110.234.52.124"
861 | - "2001:0db8:85a3:0000:0000:8a2e:0370:7334" (Ipv6)
862 |
863 | > Failing IP Rule
864 | - "210.110" – must have 4 octets
865 | - "255" – must have 4 octets
866 | - "y.y.y.y" – the only digit has allowed
867 | - "255.0.0.y" – the only digit has allowed
868 | - "666.10.10.20" – digit must between [0-255]
869 | - "4444.11.11.11" – digit must between [0-255]
870 | - "33.3333.33.3" – digit must between [0-255]
871 |
872 |
873 | ### IPv4 Rule
874 | This form rule confirms that value is an IPv4 address.
875 |
876 | > Passing IPv4 Rule
877 | - "115.42.150.37"
878 | - "192.168.0.1"
879 | - "110.234.52.124"
880 |
881 | > Failing IPv4 Rule
882 | - "210.110" – must have 4 octets
883 | - "255" – must have 4 octets
884 | - "y.y.y.y" – the only digit has allowed
885 | - "255.0.0.y" – the only digit has allowed
886 | - "666.10.10.20" – digit must between [0-255]
887 | - "4444.11.11.11" – digit must between [0-255]
888 | - "33.3333.33.3" – digit must between [0-255]
889 | - "2001:0db8:85a3:0000:0000:8a2e:0370:7334" (Ipv6)
890 |
891 |
892 | ### IPv6 Rule
893 | This form rule confirms that value is an IPv6 address.
894 |
895 | > Passing IPv6 Rule
896 | - "2001:0db8:85a3:0000:0000:8a2e:0370:7334" (Ipv6)
897 |
898 | > Failing IPv6 Rule
899 | - "210.110" – must have 4 octets
900 | - "255" – must have 4 octets
901 | - "y.y.y.y" – the only digit has allowed
902 | - "255.0.0.y" – the only digit has allowed
903 | - "666.10.10.20" – digit must between [0-255]
904 | - "4444.11.11.11" – digit must between [0-255]
905 | - "33.3333.33.3" – digit must between [0-255]
906 | - "110.234.52.124"
907 | - "192.168.0.1"
908 | - "115.42.150.37"
909 |
910 |
911 | ### Json Rule
912 | The given field value must be a Json String
913 |
914 | > Passing Json Rule
915 | ```js
916 | let data = { content: JSON.stringify({ inspire: 'love' }) };
917 | let rules = { content: 'json' };
918 |
919 | form(data).rules(rules).validate().errors().any();
920 | ```
921 |
922 | > Failing Json Rule
923 | ```js
924 | let data = { content: 'fasdf' }
925 | let rules = { content: 'json' }
926 |
927 | form(data).rules(rules).validate().errors().any();
928 | ```
929 |
930 | ### Max Rule
931 | The given field must not be more than the defined maximum limit
932 |
933 | > Passing Max Limit Rule
934 | ```js
935 | let data = { password: 'secret' }
936 | let rules = { password: 'max:10' }
937 |
938 | form(data).rules(rules).validate().errors().any();
939 | ```
940 |
941 | > Failing Max Limit Rule
942 | ```js
943 | let data = { password: 'secret'}
944 | let rules = { password: 'max:4' }
945 |
946 | form(data).rules(rules).validate().errors().any();
947 | ```
948 |
949 | ### Min Rule
950 | The given field must not be less than the defined minimum limit
951 |
952 | > Passing Min Limit Rule
953 | ```js
954 | let data = { password: 'secret' }
955 | let rules = { password: 'min:6' }
956 |
957 | form(data).rules(rules).validate().errors().any();
958 | ```
959 |
960 | > Failing Min Limit Rule
961 | ```js
962 | let data = { password: 'secret'}
963 | let rules = { password: 'min:8' }
964 |
965 | form(data).rules(rules).validate().errors().any();
966 | ```
967 |
968 |
969 | ### Not Regex Rule
970 | The given field value must NOT match the regular expression pattern
971 |
972 | > Passing Not Regex Rule
973 | ```js
974 | let data = { email: 'ex.-fn' };
975 | let rules = { email: ['not_regex:/^.+@.+$/i'] };
976 |
977 | form(data).rules(rules).validate().errors().any();
978 | ```
979 |
980 | > Failing Not Regex Rule
981 | ```js
982 |
983 |
984 | let data = { email: 'example@gmail.com'}
985 | let rules = { email: ['not_regex:/^.+@.+$/i'] }
986 |
987 | form(data).rules(rules).validate().errors().any();
988 | ```
989 |
990 |
991 | ### Not Within Rule
992 | The given field must NOT be "within" the comma delimited list of items
993 |
994 | > Passing Not Within Rule
995 | ```js
996 | let data = { language: 'PigLatin' }
997 | let rules = { language: 'not_within:German,Spanish,English,Latin' }
998 |
999 | form(data).rules(rules).validate().errors().any();
1000 | ```
1001 |
1002 | > Failing Not Within Rule
1003 | ```js
1004 | let data = { pencil: '2a'};
1005 | let rules = { pencil: 'not_within:notebook,pencil,2a,marker,sharpie,whiteboard' };
1006 |
1007 | form(data).rules(rules).validate().errors().any();
1008 | ```
1009 |
1010 | ### Number Rule
1011 | The given field must be a Number (Strict Typed Check). See Numeric For Looser Type Checking
1012 |
1013 | > Passing Number Rule
1014 | ```js
1015 | let data = { id: 15 };
1016 | let rules = { id: ['number'] };
1017 |
1018 | form(data).rules(rules).validate().errors().any();
1019 | ```
1020 |
1021 | > Failing Number Rule
1022 | ```js
1023 | let data = { id: '15'}
1024 | let rules = { id: ['number'] }
1025 |
1026 | form(data).rules(rules).validate().errors().any();
1027 | ```
1028 |
1029 | ### Numeric Rule
1030 | Determine if a value is numeric, or is a string that can properly represent a numeric
1031 |
1032 | - Numerical value, not strict number check
1033 | - Automatically attempts to cast value to numerical value.
1034 | - Validates that field value an integer, decimal, or bigInt.
1035 |
1036 | > Passing Numeric Rule
1037 | ```js
1038 | let data = { members: '25' }
1039 | let rules = { member: ['numeric'] }
1040 |
1041 | form(data).rules(rules).validate().errors().any();
1042 | ```
1043 |
1044 | > Failing Numeric Rule
1045 | ```js
1046 | let data = { members: 'yes' }
1047 | let rules = { member: ['numeric'] }
1048 |
1049 | form(data).rules(rules).validate().errors().any();
1050 | ```
1051 |
1052 |
1053 | ### Phone Rule
1054 | The given field value must be a phone number
1055 |
1056 | > Passing Phone Rule
1057 | ```js
1058 | let data = { send_sms: ['555-555-5555'] }
1059 | let rules = { send_sms: ['phone'] }
1060 |
1061 | form(data).rules(rules).validate().errors().any();
1062 | ```
1063 |
1064 | > Failing Phone Rule
1065 | ```js
1066 | let data = { send_sms: '+(3) - 4 32'}
1067 | let rules = { send_sms: ['phone'] }
1068 |
1069 | form(data).rules(rules).validate().errors().any();
1070 | ```
1071 |
1072 | > Phone Number Formats Within Testing Coverage
1073 | - +61 1 2345 6789
1074 | - +61 01 2345 6789
1075 | - 01 2345 6789
1076 | - 01-2345-6789
1077 | - (01) 2345 6789
1078 | - (01) 2345-6789
1079 | - 5555555555
1080 | - (555) 555 5555
1081 | - 555 555 5555
1082 | - +15555555555
1083 | - 555-555-5555
1084 |
1085 | > _(Any contributions welcome (vuejs-validators.js repo) for improving regex form patterns for current rules as well as adding new rules)_
1086 |
1087 |
1088 | ### Regex Rule
1089 | The given field value must match the regular expression pattern
1090 |
1091 | > Passing Regex Rule
1092 | ```js
1093 | let data = { email: 'example@gmail.com' };
1094 | let rules = { email: ['regex:/^.+@.+$/i'] };
1095 |
1096 | form(data).rules(rules).validate().errors().any();
1097 | ```
1098 |
1099 | > Failing Regex Rule
1100 | ```js
1101 | let data = { email: 'ex.-fn'}
1102 | let rules = { email: ['regex:/^.+@.+$/i'] }
1103 |
1104 | form(data).rules(rules).validate().errors().any();
1105 | ```
1106 |
1107 |
1108 | ### Required Rule
1109 | Validates that a given field exists and its value is set
1110 |
1111 | > Passing Required Rule
1112 | ```js
1113 | let data = { name: 'jules' };
1114 | let rules = { name: ['required'] };
1115 |
1116 | form(data).rules(rules).validate().errors().any();
1117 | ```
1118 |
1119 | > Failing Required Rule
1120 | ```js
1121 | let data = { name: '' };
1122 | let rules = { name: ['required'] };
1123 |
1124 | form(data).rules(rules).validate().errors().any();
1125 | ```
1126 |
1127 |
1128 | ### Same form Rule
1129 | The given field value is the same as another field value
1130 |
1131 | > Passing Same Rule
1132 | ```js
1133 | let data = { password: 'secret', confirm_password: 'secret' }
1134 | let rules = { password: 'same:confirm_password' }
1135 |
1136 | form(data).rules(rules).validate().errors().any();
1137 | ```
1138 |
1139 | > Failing Same Rule
1140 | ```js bash
1141 | let data = { password: 'asdfasdfasdf', confirm_password: 'secret' };
1142 | let rules = { password: 'same:confirm_password' };
1143 |
1144 | form(data).rules(rules).validate().errors().any();
1145 | ```
1146 |
1147 | ### Starts With Rule
1148 | The field under form must start with one of the given values.
1149 |
1150 | > Passing Starts With Rule
1151 | ```js
1152 | let data = { name: 'sammie' };
1153 | let rules = { name: 'starts_with:joe,sam,tom' };
1154 |
1155 | form(data).rules(rules).validate().errors().any();
1156 | ```
1157 |
1158 | > Failing Starts With Rule
1159 | ```js
1160 | let data = { name: 5 };
1161 | let rules = { name: 'starts_with:sl,ie,asx' };
1162 |
1163 | form(data).rules(rules).validate().errors().any();
1164 |
1165 | form.setData({ name: 'azure' })
1166 | .setRules({ name: 'starts_with:joe,sam,tom'})
1167 | .validate()
1168 | .errors()
1169 | .any();
1170 | ```
1171 |
1172 |
1173 | ### String Rule
1174 | The given field value must be a String
1175 |
1176 | > Passing String Rule
1177 | ```js
1178 | let data = { name: 'sammie' };
1179 | let rules = { name: 'string' };
1180 |
1181 | form(data).rules(rules).validate().errors().any();
1182 | ```
1183 |
1184 | > Failing String Rule
1185 | ```js
1186 | let data = { name: 54345 }
1187 | let rules = { name: 'string' }
1188 |
1189 | form(data).rules(rules).validate().errors().any();
1190 | ```
1191 |
1192 | ### Url Rule
1193 | The given field value must be an http(s) url
1194 |
1195 | > Passing Url Rule
1196 | ```js
1197 | let data = { link: 'https://cleancode.studio' };
1198 | let rules = { link: 'url' };
1199 |
1200 | form(data).rules(rules).validate().errors().any();
1201 | ```
1202 |
1203 | > Failing Url Rule
1204 | ```js
1205 | let data = { link: 'httP/ope_type@.net'}
1206 | let rules = { link: 'url' }
1207 |
1208 | form(data).rules(rules).validate().errors().any();
1209 | ```
1210 |
1211 |
1212 | ### Within Rule
1213 | The given field must be "within" the comma delimited list of items
1214 |
1215 | > Passing Within Rule
1216 | ```js
1217 | let data = { name: 'Sam' }
1218 | let rules = { name: 'within:James,Boronica,Sam,Steve,Lenny' }
1219 |
1220 | form(data).rules(rules).validate().errors().any();
1221 | ```
1222 |
1223 | > Failing Within Rule
1224 | ```js
1225 | let data = { name: 'jake'};
1226 | let rules = { name: 'within:patricia,veronica,samuel,jeviah' };
1227 |
1228 | form(data).rules(rules).validate().errors().any();
1229 | ```
1230 |
1231 |
1232 | ## Form Error Messages Api
1233 | > form.errors() Methods
1234 | - [any()](#any-errors)
1235 | - [all()](#all-errors)
1236 | - [list()](#list-errors)
1237 | - [set(errors)](#set-errors)
1238 | - [forget()](#forget-errors)
1239 | - [has(field)](#has-error)
1240 | - [get(field)](#get-error)
1241 | - [list(field)](#list-error)
1242 | - [add(field, message)](#add-error)
1243 | - [set(field, messages)](#set-field-errors)
1244 | - [forget(field)](#forget-field)
1245 | - [getValidator()](#get-errors-validator)
1246 |
1247 |
1248 | ### Any Errors
1249 | > Determine if there are "any" errors (bool)
1250 | ```js
1251 | let data = { name: '' };
1252 | let rules = { name: 'required'};
1253 | form(data).rules(rules).errors().any();
1254 | ```
1255 | ```
1256 | Output: true
1257 | ```
1258 |
1259 |
1260 | ### All Errors
1261 | > Retrieve all errors within the errors object
1262 |
1263 | ```js
1264 | let data = { name: '', email: '' };
1265 | let rules = { name: 'required', email: 'email|required' };
1266 |
1267 | form(data).rules(rules).validate().errors().all();
1268 | ```
1269 | ```
1270 | Output:
1271 |
1272 | {
1273 | name: [
1274 | 'name field is required'
1275 | ],
1276 | email: [
1277 | 'email field must be an email address',
1278 | 'email field is required'
1279 | ]
1280 | }
1281 | ```
1282 |
1283 |
1284 |
1285 | ### List Errors
1286 | > Retrieve all errors within the errors object
1287 | ```js
1288 | let data = { name: '', email: '' };
1289 | let rules = { name: 'required', email: 'email|required' };
1290 |
1291 | form(data).rules(rules).validate().errors().list();
1292 | ```
1293 | ```
1294 | Output:
1295 |
1296 | [
1297 | 'name field is required',
1298 | 'email field must be an email address',
1299 | 'email field is required'
1300 | ]
1301 | ```
1302 |
1303 |
1304 |
1305 | ### Set Errors
1306 | > Set all errors
1307 |
1308 | ```js
1309 | let data = { name: '' };
1310 | let rules = { name: 'required' };
1311 |
1312 | form(data).rules(rules).validate();
1313 |
1314 | form.errors().list();
1315 | // Output: ['name is a required field']
1316 |
1317 | form.errors().set({ notice: ['set this random error message'] });
1318 | form.errors().list()
1319 | ```
1320 | ```
1321 | Output: ['set this random error message']
1322 | ```
1323 |
1324 |
1325 | ### Forget Errors
1326 | > Forget errors and reset them to empty
1327 | ```js
1328 | let data = { name: '' };
1329 | let rules = { name: 'required' };
1330 |
1331 | form(data).rules(rules).validate().errors().list();
1332 | // Output: ['Name is a required field']
1333 |
1334 | form.errors().forget();
1335 | form.errors().list();
1336 | ```
1337 | ```
1338 | Output: []
1339 | ```
1340 |
1341 | ### Has Error
1342 | > Determine if a specific field has error messages
1343 |
1344 | ```js
1345 | let data = { name: '', email: 'example@gmail.com' };
1346 | let rules = { name: 'required', email: 'email|required' };
1347 | form(data).rules(rules).validate();
1348 |
1349 | form.errors().has('name');
1350 | form.errors().has('email');
1351 | form.errors().has('something_else');
1352 | ```
1353 | ```
1354 | Output:
1355 | has name: true
1356 | has email: false
1357 | has something_else: false
1358 | ```
1359 | ### Get Error
1360 | > Get _first_ error message for a specific field
1361 | ```js
1362 | let data = { name: '' };
1363 | let rules = { name: 'required|min:3'};
1364 |
1365 | form(data).rules(rules).validate().errors().get('name');
1366 | ```
1367 | ```
1368 | Output: "Name is a required field"
1369 | ```
1370 |
1371 | ### List Error
1372 | > List errors for a specific field
1373 | ```js
1374 | let data = { name: '' };
1375 | let rules = { name: 'required|min:3'};
1376 |
1377 | form(data).rules(rules).validate().errors().list('name');
1378 | ```
1379 | ```
1380 | Output: ['name is a required field', 'name must be longer than 3 characters']
1381 | ```
1382 |
1383 | ### Add Error
1384 | > Add error message for a specific field
1385 | ```js
1386 | let data = { name: '' };
1387 | let rules = { name: 'required|min:3'};
1388 |
1389 | form(data).rules(rules).validate().add(
1390 | 'name', 'four failures in a row. Two more failures before your locked out'
1391 | );
1392 |
1393 | form.errors().list('name');
1394 | ```
1395 | ```
1396 | Output: ['name is a required field', 'name must be longer than 3 characters', 'four failures in a row. Two more failures before your locked out']
1397 | ```
1398 |
1399 |
1400 | ### Set Error
1401 | > Set error messages for a specific field
1402 | ```js
1403 | let data = { name: '' };
1404 | let rules = { name: 'required' };
1405 |
1406 | form(data).rules(rules).validate().list('name');
1407 | ```
1408 | ```
1409 | Output: ['name is a required field']
1410 | ```
1411 | ```js
1412 | form.errors().set('name', ['random messages', 'set on', 'the name field']);
1413 | form.errors().list('name');
1414 | ```
1415 | ```
1416 | Output: ['random messages', 'set on', 'the name field']
1417 | ```
1418 |
1419 | ### Forget Error
1420 | > Forget error messages for a specific field
1421 | ```js
1422 | let data = { name: '' };
1423 | let rules = { name: 'required' };
1424 |
1425 | form(data).rules(rules).validate().list('name');
1426 | ```
1427 | ```
1428 | Output: ['name is a required field']
1429 | ```
1430 | ```js
1431 | form.errors().forget('name');
1432 | form.errors().list('name');
1433 | ```
1434 | ```
1435 | Output: []
1436 | ```
1437 |
1438 | ---
1439 |
1440 | ## Extending the Error Bag
1441 |
1442 | ---
1443 |
1444 | ---
1445 |
1446 | ### Error Bag Macro
1447 |
1448 | ---
1449 | Adds custom method on form error bag instance
1450 |
1451 | ```js
1452 | let example = form(data).rules(rules);
1453 |
1454 | let example.errors().macro('count', function () {
1455 | return this.list().length;
1456 | });
1457 |
1458 |
1459 | // example.errors().count() === example.errors().list().length
1460 | ```
1461 |
1462 |
1463 | ---
1464 |
1465 | ### Error Bag ForceMacro
1466 |
1467 | ---
1468 | Allows you to overwrite pre-defined macro and over write core error message bag functions (Use With Caution)
1469 |
1470 | ```js
1471 | let example = form({ name: '' }).rules({ name: 'required|min:3' }).validate();
1472 |
1473 | example.errors().get('name'); // Outputs: "Name is a required field"
1474 |
1475 | example.errors().forceMacro('get', function (field) {
1476 | if (this.has(field)) {
1477 | return this.list(field).join(', ') + '.';
1478 | }
1479 | });
1480 |
1481 | example.errors().get('name'); // Outputs: "Name is a required field, name must have at least 3 characters."
1482 | ```
1483 |
--------------------------------------------------------------------------------
/bundler/versioning.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | ## Versioning
4 |
5 | ---
6 |
7 | > Vuejs-Form Will Implement Semantic Versioning
8 | >
9 | > Starting (Friday, May 15, 2020)
10 |
11 | |Code Status|Stage|Rule|Example Version|
12 | |---|---|---|---|
13 | |First release|New Product|Start with 1.0.0|1.0.0|
14 | |Backward compatible bug fixes|Patch Release|Increment the third digit|1.0.1|
15 | |Backward compatible new features|Minor Release|Increment the middle digit and reset last digit to zero|1.1.0|
16 | |Changes that break backward compatibility|Major Release|Increment the first digit and reset middle and last digits to zero|2.0.0|
17 |
18 | - [Learn More About Semantic Versioning](https://docs.npmjs.com/about-semantic-versioning)
19 |
--------------------------------------------------------------------------------
/bundler/vue.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | ## Quick Vue Example
4 |
5 | ---
6 |
7 | ```html
8 |
9 |
23 |
24 | ```
25 | ```js
26 | import form from 'vuejs-form'
27 |
28 | export default {
29 | data: () => ({
30 | form: form({
31 | email: '',
32 | password: '',
33 | confirm_password: ''
34 | })
35 | .rules({
36 | email: 'email|min:5|required',
37 | password: 'same:confirm_password',
38 | confirm_password: 'min:6|required',
39 | })
40 | .messages({
41 | 'email.required': ':attribute is required',
42 | 'email.email': ':attribute must be a valid email',
43 | 'email.min': ':attribute may not have less than :min characters',
44 | 'password.same': 'Whoops, :attribute does not match the :same field',
45 | }),
46 | }),
47 |
48 | watch: {
49 | /*--------------------------------------------------------------
50 | * When Should Your Form "Validate", Providing Error Messages?
51 | *--------------------------------------------------------------
52 | * Form validates every time form data is updated. To
53 | * display errors on form submit, remove watcher &
54 | * move "this.form.validate()" over to submit()
55 | *--------------------------------------------------------------
56 | */
57 | ['form.data']: {
58 | deep: true,
59 | immediate: false,
60 | handler: (now, old) => { this.form.validate(); },
61 | }
62 | },
63 |
64 | methods: {
65 | failed() {
66 | console.log('errors: ', this.form.errors().all());
67 | },
68 | passed() {
69 | console.log('data: ', this.form.all());
70 | console.log('wrapped data: ', this.form.wrap('data'));
71 | },
72 | submit() {
73 | return this.form.errors().any() ? this.failed() : this.passed();
74 | },
75 | }
76 | }
77 | ```
78 |
--------------------------------------------------------------------------------
/bundler/vuejs-form-purpose-statement.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhorton34/vuejs-form/76474941aa5eaad773bec16b66291ec99852cd5b/bundler/vuejs-form-purpose-statement.png
--------------------------------------------------------------------------------
/code_of_conduct.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | ## Code Of Conduct
4 |
5 | ---
6 |
7 | The Clean Code Studio code of conduct is derived from Laravel code of of conduct. Any violations
8 | of the code of conduct may be reported to Zachary Horton (zak@cleancode.studio)
9 |
10 | - Participants will be tolerant of opposing views.
11 |
12 | - Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
13 |
14 | - When interpreting the words and actions of others, participants should always assume good intentions.
15 |
16 | - Behavior that can be reasonably considered harassment will not be tolerated.
17 |
--------------------------------------------------------------------------------
/dist/helpers/accessor.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**
3 | * Get value of a nested property
4 | *
5 | * @param form
6 | * @returns {*}
7 | */
8 |
9 | module.exports = function access(form) {
10 | return new Proxy(form, {
11 | get: function get(target, key) {
12 | if (Object.keys(target.data).includes(key)) {
13 | if (!Object.keys(target).includes(key)) {
14 | target[key] = null; // Initialize an empty key if the property does not exist.
15 | }
16 |
17 | return target.data[key];
18 | }
19 |
20 | return target[key];
21 | },
22 | set: function set(target, key, value) {
23 | target.data[key] = value;
24 | return target.data[key] === value;
25 | }
26 | });
27 | };
--------------------------------------------------------------------------------
/dist/helpers/dataGet.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
4 |
5 | function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
6 |
7 | function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
8 |
9 | function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
10 |
11 | function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
12 |
13 | function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
14 |
15 | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
16 |
17 | var isObject = function isObject(check) {
18 | return _typeof(check) === 'object' && Array.isArray(check) === false;
19 | };
20 |
21 | var isArray = function isArray(check) {
22 | return Array.isArray(check) === true;
23 | };
24 | /**
25 | * Get Nested Data With An Optional "*" wildcard
26 | */
27 |
28 |
29 | module.exports = function (target) {
30 | var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
31 |
32 | if (path === '') {
33 | return target;
34 | }
35 |
36 | path = Array.isArray(path) ? path : path.split('.');
37 | return path.reduce(function (value, segment) {
38 | if (segment === '*') {
39 | if (isArray(value)) {
40 | return value.reduce(function (list, item) {
41 | return [].concat(_toConsumableArray(list), [item]);
42 | }, []);
43 | } else if (isObject(value)) {
44 | return Object.values(value);
45 | } else {
46 | return value;
47 | }
48 | }
49 |
50 | if (isArray(value)) {
51 | return value.reduce(function (list, item) {
52 | if (isObject(item)) {
53 | return Object.keys(item).includes(segment) ? [].concat(_toConsumableArray(list), [item[segment]]) : _toConsumableArray(list);
54 | } else if (!isObject(item) && isArray(item)) {
55 | return [].concat(_toConsumableArray(list), [item[segment]]);
56 | } else {
57 | return [].concat(_toConsumableArray(list), [item]);
58 | }
59 | }, []);
60 | }
61 |
62 | if (isObject(value)) {
63 | return value[segment];
64 | }
65 |
66 | return value[segment] || value || null;
67 | }, target);
68 | };
--------------------------------------------------------------------------------
/dist/helpers/dataSet.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
4 |
5 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
6 |
7 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8 |
9 | var example = {
10 | family: {
11 | mom: {
12 | name: ''
13 | }
14 | }
15 | };
16 |
17 | var dataSet = function dataSet(target, value) {
18 | var path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
19 | if (path === '') return _objectSpread(_objectSpread({}, target), value);
20 | path = Array.isArray(path) ? path : path.split('.'); //
21 | // if (!path.includes('*')) {
22 | // target[path] = value;
23 | //
24 | // return target;
25 | // }
26 |
27 | var types = ['wildcard', 'object', 'array', 'value', 'empty'];
28 |
29 | var iterator = function iterator(path, loop) {
30 | return {
31 | loop: loop,
32 | last: loop.length === path.length,
33 | prev: loop === 0 ? false : loop - 1,
34 | next: loop === path.length ? false : loop + 1,
35 | left: path.length - loop
36 | };
37 | };
38 |
39 | var resolve = function resolve(target, path, iteration) {
40 | return {
41 | wildcard: path[iteration.loop] === '*',
42 | prevWildcard: iteration.prev ? path[iteration.prev] === '*' : false,
43 | nextWildcard: iteration.next ? path[iteration.next] === '*' : false,
44 | target: target,
45 | path: path
46 | };
47 | };
48 |
49 | var structure = function structure(target, path, value, segment, iterator, mapping) {
50 | return {
51 | mapping: mapping,
52 | path: target[path[iterator.loop]],
53 | prev: iterator.prev ? resolve(target, path, iterator) : false,
54 | next: iterator.next ? resolve(target, path, iterator) : false
55 | };
56 | };
57 |
58 | var loop = 0;
59 | var structures = [];
60 | path.forEach(function (segment) {
61 | structures[loop] = structure(target, path, value, segment, iterator(path, loop), structures);
62 | loop = loop + 1;
63 | });
64 | return structures;
65 | };
66 |
67 | dataSet(example, value, 'family.mom.name');
--------------------------------------------------------------------------------
/dist/helpers/exists.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**
3 | * Determine if a key value pair is missing
4 | *
5 | * @param value
6 | * @returns boolean
7 | */
8 |
9 | module.exports = function (value) {
10 | return typeof value !== "undefined";
11 | };
--------------------------------------------------------------------------------
/dist/helpers/fieldsOf.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var variadic = require('./variadic');
4 |
5 | module.exports = function (form, keys) {
6 | var properties = variadic(keys);
7 | return properties.length > 0 ? {
8 | has: function has() {
9 | return properties;
10 | },
11 | toArray: function toArray() {
12 | return Array.isArray(properties) ? properties : Array.from(properties);
13 | },
14 | isEmpty: function isEmpty() {
15 | return Array.isArray(properties) ? properties.length === 0 : Array.from(properties).length === 0;
16 | }
17 | } : {
18 | has: function has() {
19 | return form.keys();
20 | },
21 | toArray: function toArray() {
22 | return form.keys();
23 | },
24 | isEmpty: function isEmpty() {
25 | return form.keys().length === 0;
26 | }
27 | };
28 | };
--------------------------------------------------------------------------------
/dist/helpers/isEmpty.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**
3 | * Determine if a value is empty
4 | *
5 | * @param value
6 | * @returns boolean
7 | */
8 |
9 | module.exports = function (value) {
10 | if (value === null || value === '') return true;
11 | if (Array.isArray(value)) return value.length === 0;
12 |
13 | for (var key in value) {
14 | if (Object.keys(value, key)) return false;
15 | }
16 |
17 | return true;
18 | };
--------------------------------------------------------------------------------
/dist/helpers/nestedValue.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**
3 | * Get value of a nested property
4 | *
5 | * @param mainObject
6 | * @param key
7 | * @returns {*}
8 | */
9 |
10 | module.exports = function nestedValue(mainObject, key) {
11 | try {
12 | return key.split('.').reduce(function (obj, property) {
13 | return obj[property];
14 | }, mainObject);
15 | } catch (err) {
16 | return null;
17 | }
18 | };
--------------------------------------------------------------------------------
/dist/helpers/setKeys.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var variadic = require('./variadic');
4 |
5 | module.exports = function (form, keys) {
6 | var properties = variadic(keys);
7 | return properties.length > 0 ? {
8 | has: function has() {
9 | return properties;
10 | }
11 | } : {
12 | has: function has() {
13 | return form.keys();
14 | }
15 | };
16 | };
--------------------------------------------------------------------------------
/dist/helpers/setProperties.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var variadic = require('./variadic.js');
4 |
5 | module.exports = function (form, keys) {
6 | var properties = variadic(keys);
7 | return properties.length > 0 ? {
8 | orAll: function orAll() {
9 | return properties;
10 | }
11 | } : {
12 | orAll: function orAll() {
13 | return form.keys();
14 | }
15 | };
16 | };
--------------------------------------------------------------------------------
/dist/helpers/variadic.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**
3 | * Variadic helper function
4 | *
5 | * @param args
6 | * @returns {*}
7 | */
8 |
9 | module.exports = function variadic(args) {
10 | if (Array.isArray(args[0])) {
11 | return args[0];
12 | }
13 |
14 | return args;
15 | };
--------------------------------------------------------------------------------
/dist/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
4 |
5 | function VueForm(input) {
6 | if (input !== undefined && !Array.isArray(input) && _typeof(input) !== 'object') {
7 | this.data = [input];
8 | } else if (input instanceof this.constructor) {
9 | this.data = input.all();
10 | } else {
11 | this.data = input || {};
12 | }
13 | }
14 |
15 | VueForm.prototype.anyFilled = require('./methods/anyFilled');
16 | VueForm.prototype.all = require('./methods/all');
17 | VueForm.prototype["boolean"] = require('./methods/boolean');
18 | VueForm.prototype.empty = require('./methods/empty');
19 | VueForm.prototype.except = require('./methods/except');
20 | VueForm.prototype.extend = require('./methods/extend');
21 | VueForm.prototype.fill = require('./methods/fill');
22 | VueForm.prototype.filled = require('./methods/filled');
23 | VueForm.prototype.forget = require('./methods/forget');
24 | VueForm.prototype.has = require('./methods/has');
25 | VueForm.prototype.hasAny = require('./methods/hasAny');
26 | VueForm.prototype.input = require('./methods/input');
27 | VueForm.prototype.keys = require('./methods/keys');
28 | VueForm.prototype.make = require('./methods/make');
29 | VueForm.prototype.missing = require('./methods/missing');
30 | VueForm.prototype.only = require('./methods/only');
31 | VueForm.prototype.set = require('./methods/set');
32 | VueForm.prototype.toArray = require('./methods/toArray');
33 | VueForm.prototype.wrap = require('./methods/wrap');
34 | VueForm.prototype.localMacro = require('./methods/localMacro');
35 | VueForm.prototype.forceLocalMacro = require('./methods/forceLocalMacro');
36 | VueForm.prototype.macro = require('./methods/macro');
37 | VueForm.prototype.forceMacro = require('./methods/forceMacro');
38 | VueForm.prototype.proxy = require('./methods/proxy');
39 | VueForm.prototype.build = require('./methods/build');
40 | VueForm.prototype.use = require('./methods/use');
41 |
42 | var form = function form(dataOrValidatable, data) {
43 | if (typeof data === "undefined") {
44 | return new VueForm(dataOrValidatable).proxy();
45 | } else if (typeof dataOrValidatable === 'function') {
46 | return new VueForm(data).use(dataOrValidatable, {}).proxy();
47 | } else if (typeof dataOrValidatable !== 'function' && typeof data !== "undefined") {
48 | console.error("form(validatable, data): validatable must be an instance of vuejs-validators: See vuejs-form Docs");
49 | console.log("vuejs-form has a powerful, optional, validation library. vuejs-validators");
50 | console.log("vuejs-validators exports a validator function");
51 | console.log('vuejs-validators docs: https://github.com/zhorton34/vuejs-validators');
52 | console.log('vuejs-forms docs: https://github.com/zhorton34/vuejs-form');
53 | console.log('If you are trying make your vuejs-form data "validatable": ', '1: Install vuejs-validators', '2: Pass in vuejs-validators "validation" instance as the 1st parameter and the form data as the 2nd parameter (Ex: "form(validator, data)")');
54 | console.log("-----------------");
55 | console.log('To create a vuejs-form that is NOT "validatable" simply:', '1: Omit the second parameter', '2: Pass in data as the first parameter', '2: Non Validatable Form Example: form({ name: "sarah", email: "sarah.smith@gmail.com" })');
56 | }
57 |
58 | return new VueForm(data).proxy();
59 | };
60 |
61 | var validatable = require('vuejs-validators');
62 |
63 | var _require = require('vuejs-validators'),
64 | MessageBag = _require.MessageBag,
65 | MessageBagFactory = _require.MessageBagFactory;
66 |
67 | var ValidatableForm = function ValidatableForm() {
68 | var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
69 | return form(validatable, data);
70 | };
71 |
72 | module.exports = ValidatableForm;
73 | module.exports.VueForm = VueForm;
74 | module.exports.SimpleForm = form;
75 | module.exports.validator = validatable;
76 | module.exports["default"] = ValidatableForm;
77 | module.exports.ValidatableForm = ValidatableForm;
78 | module.exports.MessageBag = MessageBag;
79 | module.exports.MessageBagFactory = MessageBagFactory;
--------------------------------------------------------------------------------
/dist/methods/all.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function all() {
4 | return this.data;
5 | };
--------------------------------------------------------------------------------
/dist/methods/anyFilled.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var dataGet = require('../helpers/dataGet');
4 |
5 | var isEmpty = require('../helpers/isEmpty');
6 |
7 | var fieldsOf = require('../helpers/fieldsOf');
8 |
9 | module.exports = function anyFilled() {
10 | var _this = this;
11 |
12 | var valueFilled = function valueFilled(key) {
13 | return isEmpty(dataGet(_this.data, key)) === false;
14 | };
15 |
16 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
17 | args[_key] = arguments[_key];
18 | }
19 |
20 | return fieldsOf(this, args).has().some(valueFilled);
21 | };
--------------------------------------------------------------------------------
/dist/methods/boolean.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var dataGet = require('../helpers/dataGet.js');
4 |
5 | module.exports = function _boolean(property) {
6 | var truthy = [1, "1", true, "true", "on", "yes"];
7 | return truthy.includes(dataGet(this.data, property));
8 | };
--------------------------------------------------------------------------------
/dist/methods/build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var accessor = require('../helpers/accessor.js');
4 |
5 | module.exports = function build() {
6 | return accessor(this);
7 | };
--------------------------------------------------------------------------------
/dist/methods/empty.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var isEmpty = require('../helpers/isEmpty');
4 |
5 | var dataGet = require('../helpers/dataGet');
6 |
7 | var fieldsOf = require('../helpers/fieldsOf.js');
8 |
9 | module.exports = function empty() {
10 | var _this = this;
11 |
12 | var emptyValue = function emptyValue(key) {
13 | return isEmpty(dataGet(_this.data, key));
14 | };
15 |
16 | for (var _len = arguments.length, properties = new Array(_len), _key = 0; _key < _len; _key++) {
17 | properties[_key] = arguments[_key];
18 | }
19 |
20 | return fieldsOf(this, properties).has().some(emptyValue);
21 | };
--------------------------------------------------------------------------------
/dist/methods/except.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
4 |
5 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
6 |
7 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8 |
9 | var variadic = require('../helpers/variadic.js');
10 |
11 | module.exports = function except() {
12 | var _this = this;
13 |
14 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
15 | args[_key] = arguments[_key];
16 | }
17 |
18 | var properties = variadic(args);
19 | return Object.keys(this.data).filter(function (property) {
20 | return !properties.includes(property);
21 | }).reduce(function (only, field) {
22 | return _objectSpread(_defineProperty({}, field, _this.data[field]), only);
23 | }, {});
24 | };
--------------------------------------------------------------------------------
/dist/methods/extend.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function extend(name, callback) {
4 | if (Object.keys(this.constructor.prototype).includes(name)) {
5 | return console.error("Cant extend form with method ".concat(name, ", it already exists"));
6 | }
7 |
8 | this.constructor.prototype[name] = callback;
9 | };
--------------------------------------------------------------------------------
/dist/methods/fill.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
4 |
5 | function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
6 |
7 | function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
8 |
9 | function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
10 |
11 | function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
12 |
13 | function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
14 |
15 | module.exports = function fill() {
16 | var _this = this;
17 |
18 | var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
19 | var value = arguments.length > 1 ? arguments[1] : undefined;
20 |
21 | if (typeof value === "undefined") {
22 | Object.entries(input).forEach(function (_ref) {
23 | var _ref2 = _slicedToArray(_ref, 2),
24 | key = _ref2[0],
25 | value = _ref2[1];
26 |
27 | if (_this.empty(key)) {
28 | _this.data[key] = value;
29 | }
30 | });
31 | } else if (this.empty(input)) {
32 | this.data[input] = value;
33 | }
34 | };
--------------------------------------------------------------------------------
/dist/methods/filled.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var isEmpty = require('../helpers/isEmpty');
4 |
5 | var dataGet = require('../helpers/dataGet');
6 |
7 | var fieldsOf = require('../helpers/fieldsOf');
8 |
9 | module.exports = function filled() {
10 | var _this = this;
11 |
12 | var valueFilled = function valueFilled(key) {
13 | return isEmpty(dataGet(_this.data, key)) === false;
14 | };
15 |
16 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
17 | args[_key] = arguments[_key];
18 | }
19 |
20 | return fieldsOf(this, args).has().every(valueFilled);
21 | };
--------------------------------------------------------------------------------
/dist/methods/forceLocalMacro.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**
3 | * Similar to "localMacro" function, with ability to forcibly overwrite base prototype methods and existing macro methods (On Local Instance instead of globally)
4 | * (See Laravel Macros For In Depth Explanation)
5 | *
6 | * @param name
7 | * @param fn
8 | * @return void
9 | */
10 |
11 | module.exports = function forceMacro(name, fn) {
12 | console.warn("\n\t\tForcing macro to implement ".concat(name, " method -- Move forward with caution.\n\t\tWe recommend using \"macro\" in place of \"forceMacro\" method if you do not \n\t\tneed to override pre-existing or base behavior.\n\t "));
13 | this[name] = fn;
14 | };
--------------------------------------------------------------------------------
/dist/methods/forceMacro.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**
3 | * Similar to "macro" function, with ability to forcibly overwrite base prototype methods and existing macro methods
4 | * (See Laravel Macros For In Depth Explanation)
5 | *
6 | * @param name
7 | * @param fn
8 | * @return void
9 | */
10 |
11 | module.exports = function forceMacro(name, fn) {
12 | console.warn("\n\t\tForcing macro to implement ".concat(name, " method -- Move forward with caution.\n\t\tWe recommend using \"macro\" in place of \"forceMacro\" method if you do not \n\t\tneed to override pre-existing or base behavior.\n\t "));
13 | this[name] = fn;
14 | this.constructor.prototype[name] = fn;
15 | };
--------------------------------------------------------------------------------
/dist/methods/forget.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
4 |
5 | function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
6 |
7 | function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
8 |
9 | function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
10 |
11 | function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
12 |
13 | function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
14 |
15 | var fieldsFrom = require('../helpers/fieldsOf.js');
16 |
17 | module.exports = function forget() {
18 | for (var _len = arguments.length, list = new Array(_len), _key = 0; _key < _len; _key++) {
19 | list[_key] = arguments[_key];
20 | }
21 |
22 | var fields = fieldsFrom(this, list);
23 | this.data = fields.isEmpty() ? {} : this.except.apply(this, _toConsumableArray(fields.toArray()));
24 | };
--------------------------------------------------------------------------------
/dist/methods/has.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var dataGet = require('../helpers/dataGet');
4 |
5 | var fieldsOf = require('../helpers/fieldsOf');
6 |
7 | module.exports = function has() {
8 | var _this = this;
9 |
10 | var value = function value(key) {
11 | return dataGet(_this.data, key);
12 | };
13 |
14 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
15 | args[_key] = arguments[_key];
16 | }
17 |
18 | return fieldsOf(this, args).has().every(value);
19 | };
--------------------------------------------------------------------------------
/dist/methods/hasAny.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var dataGet = require('../helpers/dataGet');
4 |
5 | var fieldsOf = require('../helpers/fieldsOf');
6 |
7 | module.exports = function hasAny() {
8 | var _this = this;
9 |
10 | var value = function value(key) {
11 | return dataGet(_this.data, key);
12 | };
13 |
14 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
15 | args[_key] = arguments[_key];
16 | }
17 |
18 | return fieldsOf(this, args).has().some(value);
19 | };
--------------------------------------------------------------------------------
/dist/methods/input.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var isEmpty = require('../helpers/isEmpty.js');
4 |
5 | var dataGet = require('../helpers/dataGet.js');
6 |
7 | module.exports = function input(key) {
8 | var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
9 | var value = dataGet(this.data, key);
10 | return isEmpty(value) ? defaultValue : value;
11 | };
--------------------------------------------------------------------------------
/dist/methods/keys.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function keys() {
4 | return Object.keys(this.data);
5 | };
--------------------------------------------------------------------------------
/dist/methods/localMacro.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**
3 | * Add/Extend Form Functionality On Specific Instance With Custom Methods Using LocalMacro
4 | *
5 | * @param name
6 | * @param fn
7 | */
8 |
9 | module.exports = function localMacro(name, fn) {
10 | if (typeof this.constructor.prototype[name] !== 'undefined' || typeof this[name] !== 'undefined') {
11 | console.error("Cant extend form with ".concat(name, " localMacro, it already exists (use forceLocalMacro if you want to forcibly overwrite base behavior or previously set macro/localMacro"));
12 | } else {
13 | this[name] = fn;
14 | }
15 | };
--------------------------------------------------------------------------------
/dist/methods/macro.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**
3 | * Add/Extend Form Functionality With Custom Methods Using Macros (globally)
4 | *
5 | * @param name
6 | * @param fn
7 | */
8 |
9 | module.exports = function macro(name, fn) {
10 | if (Object.keys(this.constructor.prototype).includes(name)) {
11 | return console.error("Cant extend form with ".concat(name, " macro, it already exists (use forceMacro if you want to forcibly overwrite base behavior or previously set macro"));
12 | } else {
13 | this[name] = fn;
14 | this.constructor.prototype[name] = fn;
15 | }
16 | };
--------------------------------------------------------------------------------
/dist/methods/make.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var accessor = require('../helpers/accessor');
4 |
5 | module.exports = function make(input) {
6 | return accessor(new this.constructor(input));
7 | };
--------------------------------------------------------------------------------
/dist/methods/missing.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var exists = require('../helpers/exists');
4 |
5 | var dataGet = require('../helpers/dataGet');
6 |
7 | var fieldsOf = require('../helpers/fieldsOf');
8 |
9 | module.exports = function missing() {
10 | var _this = this;
11 |
12 | var missing = function missing(key) {
13 | return !exists(dataGet(_this.data, key));
14 | };
15 |
16 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
17 | args[_key] = arguments[_key];
18 | }
19 |
20 | return fieldsOf(this, args).has().some(missing);
21 | };
--------------------------------------------------------------------------------
/dist/methods/only.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
4 |
5 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
6 |
7 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8 |
9 | var variadic = require('../helpers/variadic');
10 |
11 | module.exports = function only() {
12 | var _this = this;
13 |
14 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
15 | args[_key] = arguments[_key];
16 | }
17 |
18 | var properties = variadic(args);
19 | return properties.reduce(function (only, field) {
20 | return _objectSpread(_defineProperty({}, field, _this.data[field]), only);
21 | }, {});
22 | };
--------------------------------------------------------------------------------
/dist/methods/override.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**
3 | * Add/Extend Form Functionality With Custom Methods Using Macros
4 | *
5 | * @param name
6 | * @param fn
7 | */
8 |
9 | module.exports = function override(name, fn) {
10 | if (Object.keys(this.constructor.prototype).includes(name)) {
11 | console.warn("\n\t\t\tOverriding default form method ".concat(name, ". With customized functionality. \n\t\t\tProceed with caution, you could break EVERYTHING...(Hopefully wont though :)\n\t\t"));
12 | }
13 |
14 | this.constructor.prototype[name] = fn;
15 | };
--------------------------------------------------------------------------------
/dist/methods/proxy.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var accessor = require('../helpers/accessor.js');
4 |
5 | module.exports = function proxy() {
6 | return accessor(this);
7 | };
--------------------------------------------------------------------------------
/dist/methods/set.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
4 |
5 | function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
6 |
7 | function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
8 |
9 | function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
10 |
11 | function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
12 |
13 | function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
14 |
15 | module.exports = function set() {
16 | var _this = this;
17 |
18 | var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
19 | var value = arguments.length > 1 ? arguments[1] : undefined;
20 |
21 | if (typeof value === "undefined") {
22 | Object.entries(input).forEach(function (_ref) {
23 | var _ref2 = _slicedToArray(_ref, 2),
24 | key = _ref2[0],
25 | value = _ref2[1];
26 |
27 | _this.data[key] = value;
28 | });
29 | } else {
30 | this.data[input] = value;
31 | }
32 | };
--------------------------------------------------------------------------------
/dist/methods/toArray.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
4 |
5 | function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
6 |
7 | function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
8 |
9 | function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
10 |
11 | function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
12 |
13 | function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
14 |
15 | module.exports = function toArray() {
16 | return Object.entries(this.data).map(function (_ref) {
17 | var _ref2 = _slicedToArray(_ref, 2),
18 | key = _ref2[0],
19 | value = _ref2[1];
20 |
21 | return {
22 | key: key,
23 | value: value
24 | };
25 | });
26 | };
--------------------------------------------------------------------------------
/dist/methods/use.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**
3 | * Use Validator (vuejs-validators)
4 | *
5 | * @param validatable
6 | * @param options
7 | * @returns {*}
8 | */
9 |
10 | module.exports = function use(validatable) {
11 | var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
12 |
13 | this.setValidator = function () {
14 | var rules = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
15 | var messages = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
16 | var translator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
17 | this.validatorInstance = validatable(this.data, rules, messages, translator);
18 | return this;
19 | };
20 |
21 | this.hasValidator = function () {
22 | return typeof this.validatorInstance !== 'undefined';
23 | };
24 |
25 | this.rules = function () {
26 | var rules = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
27 |
28 | if (this.validator()) {
29 | this.validator().setRules(rules);
30 | } else {
31 | this.validatorInstance = validatable(this.data, rules);
32 | }
33 |
34 | return this;
35 | };
36 |
37 | this.messages = function () {
38 | var messages = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
39 | var rules = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
40 |
41 | if (this.hasValidator()) {
42 | this.validator().setMessages(messages);
43 | } else {
44 | this.validatorInstance = validatable(this.data, rules, messages);
45 | }
46 |
47 | return this;
48 | };
49 |
50 | this.validate = function () {
51 | this.validator().setData(this.data);
52 | this.validator().validate();
53 | return this;
54 | };
55 |
56 | this.validator = function () {
57 | return this.validatorInstance;
58 | };
59 |
60 | this.errors = function () {
61 | return this.validator().errors();
62 | };
63 |
64 | this.setValidator(options);
65 | return this;
66 | };
--------------------------------------------------------------------------------
/dist/methods/wrap.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
4 |
5 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
6 |
7 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8 |
9 | module.exports = function wrap(key) {
10 | return key.split('.').reverse().reduce(function (payload, property) {
11 | return _defineProperty({}, property, _objectSpread({}, payload));
12 | }, this.data);
13 | };
--------------------------------------------------------------------------------
/docs/.vuepress/config.js:
--------------------------------------------------------------------------------
1 | const { readdirSync } = require('fs');
2 |
3 | module.exports = {
4 | title: 'vuejs-form',
5 | description: 'Simplified, dependency free wrapper for easily interacting with form input data.',
6 | themeConfig: {
7 | nav: [
8 | { text: 'Home', link: '/' },
9 | { text: 'Installation', link: '/installation.md' },
10 | { text: 'Usage', link: '/usage.md' },
11 | { text: 'API', link: '/api.md' },
12 | { text: 'GitHub', link: 'https://github.com/zhorton34/vuejs-form.js' },
13 | ],
14 | sidebar: [{
15 | title: 'Get started',
16 | collapsable:false,
17 | children: [
18 | 'installation',
19 | 'usage',
20 | ],
21 | }, {
22 | title: 'API',
23 | collapsable: false,
24 | children: readdirSync('docs/api', 'utf-8').map(file => `/api/${file}`),
25 | }],
26 | },
27 | };
28 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | actionText: Get Started →
4 | actionLink: /installation/
5 | features:
6 | - title: 📄 Simplified API
7 | details: Enjoy Building Forms In Vue
8 | - title: 🏗 Extendable
9 | details: Want to customize? vuejs-form.js can be extended using extends.
10 | - title: Vuejs + Forms
11 | details: Simplify Vue Forms With This Package Inspired By Laravel $request->input() and set up based on Collection.js
12 | footer: MIT Licensed | Copyright © Zachary Horton
13 | ---
--------------------------------------------------------------------------------
/docs/api/all.md:
--------------------------------------------------------------------------------
1 | # `all()`
2 |
3 | The all method returns the underlying input object represented by the form:
4 |
5 | ```js
6 | form({ name: 'sarah', email: 'sarah@gmail.com' }).all();
7 |
8 | // { name: 'sarah', email: 'sarah@gmail.com' }
9 | ```
10 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/all.js)
11 |
--------------------------------------------------------------------------------
/docs/api/boolean.md:
--------------------------------------------------------------------------------
1 | # `boolean(property)`
2 |
3 | The boolean method determines if the given field has a truthy or falsy values:
4 | #### Truthy values: true, "true", "yes", "on", "1", 1
5 | #### Falsy values: Everything else
6 |
7 | ```js
8 |
9 | const LoginForm = form({
10 | name: '',
11 | email: '',
12 | terms: ''
13 | })
14 |
15 | LoginForm.terms = true
16 | LoginForm.boolean('terms') // true
17 |
18 | LoginForm.terms = 'true'
19 | LoginForm.boolean('terms') // true
20 |
21 | LoginForm.terms = 'yes'
22 | LoginForm.boolean('terms') // true
23 |
24 | LoginForm.terms = 'on'
25 | LoginForm.boolean('terms') // true
26 |
27 | LoginForm.terms = "1"
28 | LoginForm.boolean('terms') // true
29 |
30 | LoginForm.terms = 1
31 | LoginForm.boolean('terms') // true
32 | ```
33 |
34 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/boolean.js)
35 |
--------------------------------------------------------------------------------
/docs/api/empty.md:
--------------------------------------------------------------------------------
1 | # `empty(one, two, three, ...)`
2 |
3 | The empty method determines if the input property exists but the value is empty:
4 |
5 | ```js
6 | const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });
7 |
8 | ExampleForm.empty('name') // false
9 | ExampleForm.empty('name', 'email') // false
10 |
11 | ExampleForm.empty('id') // true
12 | ```
13 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/empty.js)
14 |
--------------------------------------------------------------------------------
/docs/api/except.md:
--------------------------------------------------------------------------------
1 | # `except(one, two, three, ...)`
2 |
3 | The except method grabs all of the inputs except the properties passed in:
4 |
5 | ```js
6 | const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });
7 |
8 | ExampleForm.except('id')
9 | /**
10 | * { name: 'sarah', email: 'sarah@gmail.com' }
11 | */
12 |
13 | ExampleForm.except('id', 'name')
14 | /**
15 | * { email: 'sarah@gmail.com' }
16 | */
17 | ```
18 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/except.js)
19 |
20 |
--------------------------------------------------------------------------------
/docs/api/fill.md:
--------------------------------------------------------------------------------
1 | # `fill({ key: value, keyTwo: valueTwo, etc... })`
2 |
3 | The fill method allows you to fill in new or empty values without overriding existing values:
4 |
5 | ```js
6 | const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });
7 |
8 | ExampleForm.fill({
9 | id: 2,
10 | name: 'tim',
11 | email: 'tim@gmail.com'
12 | })
13 |
14 | ExampleForm.all()
15 | // { id: 2, name: 'sarah', email: 'sarah@gmail.com' }
16 | ```
17 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/fill.js)
18 |
--------------------------------------------------------------------------------
/docs/api/filled.md:
--------------------------------------------------------------------------------
1 | # `filled(propertyOne, propertyTwo, etc...)`
2 |
3 | The filled method determine if a value is filled (AKA not empty):
4 |
5 | ```js
6 | const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });
7 |
8 | ExampleForm.filled('id', 'name') // false
9 | ExampleForm.filled('name', 'email') // true
10 | ```
11 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/filled.js)
12 |
--------------------------------------------------------------------------------
/docs/api/forceMacro.md:
--------------------------------------------------------------------------------
1 | # `forceMacro(key, fn)`
2 | forceMacro can be used to extend form object and FORCIBLY OVERWRITE base form behavior (Use VERY cautiously and prefer macro over forceMacro)
3 |
4 | _NOTE: Use forceLocalMacro if you only want to extend a specific form instance instead of all form instances._
5 |
6 | ```js
7 | import form from 'vuejs-form';
8 |
9 | form().forceMacro('all', function () {
10 | return this.keys().reduce((list, field) => ({
11 | ...list,
12 | [field]: {
13 | name: field,
14 | value: this.data[field],
15 | errors: this.errors().list(field),
16 | }
17 | }),
18 | {});
19 | })
20 |
21 | form({ name: 'sam' }).rules({ name: 'required' }).validate();
22 | ```
23 |
24 | ```
25 | # forceMacro implementation of form.all() Outputs
26 | {
27 | name: {
28 | value: 'sam',
29 | name: 'name',
30 | errors: ['Name field is required']
31 | }
32 | }
33 | ```
34 |
35 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/forceMacro.js)
36 |
37 |
--------------------------------------------------------------------------------
/docs/api/forget.md:
--------------------------------------------------------------------------------
1 | # `forget(propertyOne, propertyTwo, etc...)`
2 |
3 | The forget method will remove or "forget" a key value pair from the form input data
4 |
5 | ```js
6 | const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });
7 |
8 | ExampleForm.forget('id', 'name')
9 | ExampleForm.all() // { email: 'sarah@gmail.com' }
10 | ```
11 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/forget.js)
12 |
--------------------------------------------------------------------------------
/docs/api/has.md:
--------------------------------------------------------------------------------
1 | # `has(propertyOne, propertyTwo, etc...)`
2 |
3 | The has method will determine if a key exists within the form input data
4 |
5 | ```js
6 | const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });
7 |
8 | ExampleForm.has('id', 'name') // true
9 | ExampleForm.has('something', 'id', 'name') // false
10 | ```
11 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/has.js)
12 |
--------------------------------------------------------------------------------
/docs/api/hasAny.md:
--------------------------------------------------------------------------------
1 | # `hasAny(propertyOne, propertyTwo, etc...)`
2 |
3 | The hasAny method will determine if a key has any of the given properties within the form input data
4 |
5 | ```js
6 | const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });
7 |
8 | ExampleForm.hasAny('id', 'name') // true
9 | ExampleForm.hasAny('something', 'id', 'name') // true
10 | ```
11 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/hasAny.js)
12 |
--------------------------------------------------------------------------------
/docs/api/input.md:
--------------------------------------------------------------------------------
1 | # `input(property, default = false)`
2 |
3 | The input method will resolve a given input value or default to false. You can define a default as the second parameter
4 |
5 | ```js
6 | const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });
7 |
8 | ExampleForm.input('id') // false
9 | ExampleForm.input('id', 1) // 1
10 | ExampleForm.input('name', 'tim') // sarah
11 | ```
12 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/input.js)
13 |
--------------------------------------------------------------------------------
/docs/api/keys.md:
--------------------------------------------------------------------------------
1 | # `keys()`
2 |
3 | The keys method will resolve an array of the input keys
4 |
5 | ```js
6 | const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });
7 |
8 | ExampleForm.keys() // ['id', 'name', 'email']
9 | ```
10 |
11 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/keys.js)
12 |
--------------------------------------------------------------------------------
/docs/api/macro.md:
--------------------------------------------------------------------------------
1 | # `macro(key, fn)`
2 |
3 | The macro method can be used to extend the forms base behavior with custom methods/functions
4 |
5 | _NOTE: Use localMacro if you only want to extend a specific form instance instead of all form instances._
6 |
7 | ```js
8 | import form from 'vuejs-form';
9 |
10 | form(data).macro('count', () => {
11 | return this.keys().length;
12 | });
13 |
14 | // form.count() === form.keys().length
15 | ```
16 |
17 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/macro.js)
18 |
19 |
--------------------------------------------------------------------------------
/docs/api/make.md:
--------------------------------------------------------------------------------
1 | # `make({ ... })`
2 |
3 | The make method will "make" a new form when used on the underlying class (With the proxy used on all forms)
4 |
5 | ```js
6 | import { VueForm } from 'vuejs-form'
7 |
8 | const ExampleForm = VueForm.make({ id: '', name: 'sarah', email: 'sarah@gmail.com' })
9 | ExampleForm.all() // { id: '', name: 'sarah', email: 'sarah@gmail.com' }
10 | ```
11 |
12 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/make.js)
13 |
--------------------------------------------------------------------------------
/docs/api/missing.md:
--------------------------------------------------------------------------------
1 | # `missing(propertyOne, propertyTwo, ...)`
2 |
3 | The missing method will determine if the form is missing the following properties
4 |
5 | ```js
6 | const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' })
7 |
8 | ExampleForm.missing('id') // false
9 | ExampleForm.missing('something') // true
10 | ExampleForm.missing('name', 'email') // false
11 | ExampleForm.missing('name', 'email', 'something') // true
12 | ```
13 |
14 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/missing.js)
15 |
--------------------------------------------------------------------------------
/docs/api/only.md:
--------------------------------------------------------------------------------
1 | # `only(propertyOne, propertyTwo, ...)`
2 |
3 | The only method will return an object of "only" the input properties you defined
4 |
5 | ```js
6 | const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' })
7 |
8 | ExampleForm.only('name', 'email') // { name: 'sarah', email: 'sarah@gmail.com' }
9 | ExampleForm.only('id', 'name') // { id: '', name: 'sarah' }
10 | ExampleForm.only('id') // { id: '' }
11 | ```
12 |
13 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/only.js)
14 |
--------------------------------------------------------------------------------
/docs/api/set.md:
--------------------------------------------------------------------------------
1 | # `set({ key: value, keyTwo: valueTwo, etc... })`
2 |
3 | The set method allows you to set new and override previous values:
4 |
5 | ```js
6 | const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });
7 |
8 | ExampleForm.set({
9 | id: 2,
10 | name: 'tim',
11 | email: 'tim@gmail.com',
12 | password: 'secret',
13 | })
14 |
15 | ExampleForm.all()
16 | // { id: 2, name: 'tim', email: 'tim@gmail.com', password: 'secret' }
17 | ```
18 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/set.js)
19 |
--------------------------------------------------------------------------------
/docs/api/toArray.md:
--------------------------------------------------------------------------------
1 | # `toArray()`
2 |
3 | The toArray method transforms the input into an array of key value pair objects:
4 |
5 | ```js
6 | const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });
7 |
8 | ExampleForm.toArray()
9 | /**
10 | [
11 | { key: 'id', value: '' },
12 | { key: 'name', value: 'sarah' },
13 | { key: 'email', value: 'sarah@gmail.com' }
14 | ]
15 | */
16 |
17 | ```
18 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/toArray.js)
19 |
--------------------------------------------------------------------------------
/docs/api/wrap.md:
--------------------------------------------------------------------------------
1 | # `wrap(key)`
2 |
3 | The wrap method allows you to wrap the input within a given object key:
4 |
5 | ```js
6 | const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });
7 |
8 | ExampleForm.wrap('data')
9 | /**
10 | {
11 | data: {
12 | id: '',
13 | name: 'sarah',
14 | email: 'sarah@gmail.com'
15 | }
16 | }
17 | */
18 |
19 | ```
20 | [View source on GitHub](https://github.com/zhorton34/vuejs-form.js/blob/master/src/methods/wrap.js)
21 |
--------------------------------------------------------------------------------
/mix-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "/dist/index.js": "/dist/index.js"
3 | }
4 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vuejs-form",
3 | "version": "1.3.0",
4 | "description": "Form wrapper simplifying developer ability to access, check, fill, and pass input data",
5 | "main": "dist/index.js",
6 | "scripts": {
7 | "all": "npm run build && npm test",
8 | "pretest": "npm run transpile",
9 | "test": "mocha test/tests.js",
10 | "transpile": "babel src --quiet --out-dir dist",
11 | "readme": "node bundler/bundle.js",
12 | "bundle": "webpack-cli dist/index.js --output build/vuejs-form.js --mode development --output-library form",
13 | "uglify": "uglifyjs build/vuejs-form.js --compress --mangle --output build/vuejs-form.min.js",
14 | "build": "npm run transpile && npm run bundle && npm run uglify && npm run readme",
15 | "coverage": "npm run transpile && nyc mocha test/tests.js",
16 | "reporter": "nyc report --reporter=html",
17 | "docs:dev": "vuepress dev docs",
18 | "docs:build": "vuepress build docs",
19 | "prepublishOnly": "npm run all"
20 | },
21 | "repository": {
22 | "type": "git",
23 | "url": "git+https://github.com/zhorton34/vuejs-form.git"
24 | },
25 | "keywords": [
26 | "vue form",
27 | "form",
28 | "vue",
29 | "vuejs form",
30 | "vuejs forms",
31 | "form vuejs",
32 | "vue forms package",
33 | "vue form input",
34 | "vue validation",
35 | "vuejs validators",
36 | "validation with vuejs",
37 | "validators",
38 | "data validation",
39 | "javascript validation",
40 | "vue validators",
41 | "reactive vue validation",
42 | "vue rules",
43 | "validator javascript",
44 | "that vue validator",
45 | "javascript validation rules",
46 | "vuejs validation messages",
47 | "vue js validation rules",
48 | "simple vuejs validators"
49 | ],
50 | "author": "Zachary Horton",
51 | "license": "MIT",
52 | "babel": {
53 | "presets": [
54 | "@babel/preset-env"
55 | ]
56 | },
57 | "bugs": {
58 | "url": "https://github.com/zhorton34/vuejs-form/issues"
59 | },
60 | "homepage": "https://github.com/zhorton34/vuejs-form#readme",
61 | "devDependencies": {
62 | "@babel/cli": "^7.2.3",
63 | "@babel/core": "^7.2.2",
64 | "@babel/polyfill": "^7.8.3",
65 | "@babel/preset-env": "^7.9.6",
66 | "benchmark": "^2.1.0",
67 | "chai": "^4.1.2",
68 | "hoax.js": "^1.0.0",
69 | "mocha": "^3.5.2",
70 | "nyc": "^11.0.2",
71 | "uglify-js": "^3.2.2",
72 | "vuejs-validators": "^1.1.7",
73 | "webpack": "^4.43.0",
74 | "webpack-cli": "^3.3.11"
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/helpers/accessor.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Get value of a nested property
5 | *
6 | * @param form
7 | * @returns {*}
8 | */
9 | module.exports = function access(form) {
10 | return new Proxy(form, {
11 | get (target, key){
12 | if(Object.keys(target.data).includes(key)) {
13 |
14 | if(!Object.keys(target).includes(key)) {
15 | target[key] = null; // Initialize an empty key if the property does not exist.
16 | }
17 |
18 | return target.data[key];
19 | }
20 |
21 | return target[key]
22 | },
23 |
24 | set (target, key, value) {
25 | target.data[key] = value;
26 |
27 | return target.data[key] === value;
28 | }
29 | })
30 | };
31 |
--------------------------------------------------------------------------------
/src/helpers/dataGet.js:
--------------------------------------------------------------------------------
1 | const isObject = check => typeof check === 'object' && Array.isArray(check) === false;
2 | const isArray = check => Array.isArray(check) === true;
3 |
4 | /**
5 | * Get Nested Data With An Optional "*" wildcard
6 | */
7 | module.exports = function (target, path = '') {
8 | if (path === '') {
9 | return target;
10 | }
11 |
12 | path = Array.isArray(path) ? path : path.split('.');
13 |
14 | return path.reduce((value, segment) => {
15 | if (segment === '*') {
16 | if (isArray(value)) {
17 | return value.reduce((list, item) => [...list, item], [])
18 | } else if (isObject(value)) {
19 | return Object.values(value);
20 | } else {
21 | return value
22 | }
23 | }
24 |
25 | if (isArray(value)) {
26 | return value.reduce((list, item) => {
27 | if (isObject(item)) {
28 | return Object.keys(item).includes(segment) ? [...list, item[segment]] : [...list];
29 | } else if (!isObject(item) && isArray(item)) {
30 | return [...list, item[segment]]
31 | } else {
32 | return [...list, item]
33 | }
34 | }, []);
35 | }
36 |
37 | if (isObject(value)) {
38 | return value[segment]
39 | }
40 |
41 | return value[segment] || value || null;
42 |
43 | }, target)
44 | };
45 |
--------------------------------------------------------------------------------
/src/helpers/dataSet.js:
--------------------------------------------------------------------------------
1 | const example = {
2 | family: {
3 | mom: { name: '' }
4 | }
5 | };
6 | const dataSet = function(target, value, path = '') {
7 | if (path === '') return { ...target, ...value };
8 |
9 | path = Array.isArray(path) ? path : path.split('.');
10 | //
11 | // if (!path.includes('*')) {
12 | // target[path] = value;
13 | //
14 | // return target;
15 | // }
16 |
17 |
18 | const types = ['wildcard', 'object', 'array', 'value', 'empty'];
19 |
20 | const iterator = (path, loop) => ({
21 | loop,
22 | last: loop.length === path.length,
23 | prev: loop === 0 ? false : loop - 1,
24 | next: loop === path.length ? false : loop + 1,
25 | left: path.length - loop
26 | });
27 |
28 | const resolve = (target, path, iteration) => ({
29 | wildcard: path[iteration.loop] === '*',
30 | prevWildcard: iteration.prev ? path[iteration.prev] === '*' : false,
31 | nextWildcard: iteration.next ? path[iteration.next] === '*' : false,
32 | target,
33 | path,
34 | });
35 | const structure = (target, path, value, segment, iterator, mapping) => ({
36 | mapping,
37 | path: target[path[iterator.loop]],
38 | prev: iterator.prev ? resolve(target, path, iterator) : false,
39 | next: iterator.next ? resolve(target, path, iterator) : false,
40 | });
41 |
42 | let loop = 0;
43 | let structures = [];
44 | path.forEach(segment => {
45 | structures[loop] = structure(target, path, value, segment, iterator(path, loop), structures);
46 |
47 | loop = loop+1;
48 | });
49 |
50 | return structures;
51 |
52 | };
53 |
54 | dataSet(example, value, 'family.mom.name');
55 |
--------------------------------------------------------------------------------
/src/helpers/exists.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Determine if a key value pair is missing
5 | *
6 | * @param value
7 | * @returns boolean
8 | */
9 | module.exports = function (value) {
10 | return typeof value !== "undefined";
11 | };
12 |
--------------------------------------------------------------------------------
/src/helpers/fieldsOf.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const variadic = require('./variadic');
3 |
4 | module.exports = function (form, keys) {
5 | const properties = variadic(keys);
6 |
7 | return properties.length > 0
8 | ? {
9 | has: () => properties,
10 | toArray: () => Array.isArray(properties) ? properties : Array.from(properties),
11 | isEmpty: () => Array.isArray(properties) ? properties.length === 0 : Array.from(properties).length === 0
12 | }
13 | : {
14 | has: () => form.keys(),
15 | toArray: () => form.keys(),
16 | isEmpty: () => form.keys().length === 0
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/src/helpers/isEmpty.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Determine if a value is empty
5 | *
6 | * @param value
7 | * @returns boolean
8 | */
9 | module.exports = function (value) {
10 | if (value === null || value === '') return true;
11 | if (Array.isArray(value)) return value.length === 0;
12 | for (const key in value) if (Object.keys(value, key)) return false;
13 | return true;
14 | };
15 |
--------------------------------------------------------------------------------
/src/helpers/nestedValue.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Get value of a nested property
5 | *
6 | * @param mainObject
7 | * @param key
8 | * @returns {*}
9 | */
10 | module.exports = function nestedValue(mainObject, key) {
11 | try {
12 | return key.split('.').reduce((obj, property) => obj[property], mainObject);
13 | } catch (err) {
14 | return null;
15 | }
16 | };
--------------------------------------------------------------------------------
/src/helpers/variadic.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Variadic helper function
5 | *
6 | * @param args
7 | * @returns {*}
8 | */
9 | module.exports = function variadic(args) {
10 | if (Array.isArray(args[0])) {
11 | return args[0];
12 | }
13 |
14 | return args;
15 | };
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function VueForm(input) {
4 | if (input !== undefined && !Array.isArray(input) && typeof input !== 'object') {
5 | this.data = [input];
6 | } else if (input instanceof this.constructor) {
7 | this.data = input.all();
8 | } else {
9 | this.data = input || {};
10 | }
11 | }
12 |
13 | VueForm.prototype.anyFilled = require('./methods/anyFilled');
14 | VueForm.prototype.all = require('./methods/all');
15 | VueForm.prototype.boolean = require('./methods/boolean');
16 | VueForm.prototype.empty = require('./methods/empty');
17 | VueForm.prototype.except = require('./methods/except');
18 | VueForm.prototype.extend = require('./methods/extend');
19 | VueForm.prototype.fill = require('./methods/fill');
20 | VueForm.prototype.filled = require('./methods/filled');
21 | VueForm.prototype.forget = require('./methods/forget');
22 | VueForm.prototype.has = require('./methods/has');
23 | VueForm.prototype.hasAny = require('./methods/hasAny');
24 | VueForm.prototype.input = require('./methods/input');
25 | VueForm.prototype.keys = require('./methods/keys');
26 | VueForm.prototype.make = require('./methods/make');
27 | VueForm.prototype.missing = require('./methods/missing');
28 | VueForm.prototype.only = require('./methods/only');
29 | VueForm.prototype.set = require('./methods/set');
30 | VueForm.prototype.toArray = require('./methods/toArray');
31 | VueForm.prototype.wrap = require('./methods/wrap');
32 | VueForm.prototype.localMacro = require('./methods/localMacro');
33 | VueForm.prototype.forceLocalMacro = require('./methods/forceLocalMacro');
34 | VueForm.prototype.macro = require('./methods/macro');
35 | VueForm.prototype.forceMacro = require('./methods/forceMacro');
36 | VueForm.prototype.proxy = require('./methods/proxy');
37 | VueForm.prototype.build = require('./methods/build');
38 | VueForm.prototype.use = require('./methods/use');
39 |
40 | const form = function (dataOrValidatable, data) {
41 | if (typeof data === "undefined") {
42 | return (new VueForm(dataOrValidatable)).proxy();
43 | }
44 | else if (typeof dataOrValidatable === 'function') {
45 | return (new VueForm(data)).use(dataOrValidatable, {}).proxy();
46 | }
47 | else if (typeof dataOrValidatable !== 'function' && typeof data !== "undefined") {
48 | console.error(`form(validatable, data): validatable must be an instance of vuejs-validators: See vuejs-form Docs`);
49 | console.log(`vuejs-form has a powerful, optional, validation library. vuejs-validators`);
50 | console.log(`vuejs-validators exports a validator function`);
51 | console.log('vuejs-validators docs: https://github.com/zhorton34/vuejs-validators');
52 | console.log('vuejs-forms docs: https://github.com/zhorton34/vuejs-form');
53 | console.log(
54 | 'If you are trying make your vuejs-form data "validatable": ',
55 | '1: Install vuejs-validators',
56 | '2: Pass in vuejs-validators "validation" instance as the 1st parameter and the form data as the 2nd parameter (Ex: "form(validator, data)")'
57 | );
58 | console.log("-----------------");
59 | console.log(
60 | 'To create a vuejs-form that is NOT "validatable" simply:',
61 | '1: Omit the second parameter',
62 | '2: Pass in data as the first parameter',
63 | '2: Non Validatable Form Example: form({ name: "sarah", email: "sarah.smith@gmail.com" })',
64 | );
65 | }
66 |
67 | return (new VueForm(data)).proxy();
68 | };
69 |
70 | const validatable = require('vuejs-validators');
71 | const { MessageBag, MessageBagFactory } = require('vuejs-validators');
72 |
73 |
74 | const ValidatableForm = function ValidatableForm(data = {}) {
75 | return form(validatable, data);
76 | };
77 |
78 | module.exports = ValidatableForm;
79 | module.exports.VueForm = VueForm;
80 | module.exports.SimpleForm = form;
81 | module.exports.validator = validatable;
82 | module.exports.default = ValidatableForm;
83 | module.exports.ValidatableForm = ValidatableForm;
84 |
85 | module.exports.MessageBag = MessageBag;
86 | module.exports.MessageBagFactory = MessageBagFactory;
87 |
88 |
--------------------------------------------------------------------------------
/src/methods/all.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function all() {
4 | return this.data;
5 | };
--------------------------------------------------------------------------------
/src/methods/anyFilled.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const dataGet = require('../helpers/dataGet');
4 | const isEmpty = require('../helpers/isEmpty');
5 | const fieldsOf = require('../helpers/fieldsOf');
6 |
7 | module.exports = function anyFilled(...args) {
8 | const valueFilled = key => isEmpty(dataGet(this.data, key)) === false;
9 |
10 | return fieldsOf(this, args).has().some(valueFilled);
11 | };
12 |
--------------------------------------------------------------------------------
/src/methods/boolean.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const dataGet = require('../helpers/dataGet.js');
4 |
5 | module.exports = function boolean(property) {
6 | const truthy = [1, "1", true, "true", "on", "yes"];
7 |
8 | return truthy.includes(dataGet(this.data, property));
9 | };
10 |
--------------------------------------------------------------------------------
/src/methods/build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const accessor = require('../helpers/accessor.js');
4 |
5 | module.exports = function build() {
6 | return accessor(this);
7 | };
8 |
--------------------------------------------------------------------------------
/src/methods/empty.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const isEmpty = require('../helpers/isEmpty');
4 | const dataGet = require('../helpers/dataGet');
5 | const fieldsOf = require('../helpers/fieldsOf.js');
6 |
7 | module.exports = function empty(...properties) {
8 | const emptyValue = key => isEmpty(dataGet(this.data, key));
9 |
10 | return fieldsOf(this, properties).has().some(emptyValue);
11 | };
12 |
--------------------------------------------------------------------------------
/src/methods/except.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const variadic = require('../helpers/variadic.js');
4 |
5 | module.exports = function except(...args) {
6 | const properties = variadic(args);
7 |
8 | return Object.keys(this.data)
9 | .filter(property => !properties.includes(property))
10 | .reduce((only, field) => ({ [field]: this.data[field], ...only }), {});
11 | };
12 |
--------------------------------------------------------------------------------
/src/methods/extend.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function extend(name, callback) {
4 | if (Object.keys(this.constructor.prototype).includes(name)) {
5 | return console.error(`Cant extend form with method ${name}, it already exists`);
6 | }
7 |
8 | this.constructor.prototype[name] = callback;
9 | };
10 |
--------------------------------------------------------------------------------
/src/methods/fill.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function fill(input = {}, value) {
4 |
5 | if (typeof value === "undefined") {
6 | Object.entries(input).forEach(([key, value]) => {
7 | if (this.empty(key)) {
8 | this.data[key] = value;
9 | }
10 | });
11 | } else if (this.empty(input)) {
12 | this.data[input] = value;
13 | }
14 | };
15 |
--------------------------------------------------------------------------------
/src/methods/filled.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const isEmpty = require('../helpers/isEmpty');
4 | const dataGet = require('../helpers/dataGet');
5 | const fieldsOf = require('../helpers/fieldsOf');
6 |
7 | module.exports = function filled(...args) {
8 | const valueFilled = key => isEmpty(dataGet(this.data, key)) === false;
9 |
10 | return fieldsOf(this, args).has().every(valueFilled);
11 | };
12 |
--------------------------------------------------------------------------------
/src/methods/forceLocalMacro.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | /**
5 | * Similar to "localMacro" function, with ability to forcibly overwrite base prototype methods and existing macro methods (On Local Instance instead of globally)
6 | * (See Laravel Macros For In Depth Explanation)
7 | *
8 | * @param name
9 | * @param fn
10 | * @return void
11 | */
12 | module.exports = function forceMacro(name, fn) {
13 | console.warn(`
14 | Forcing macro to implement ${name} method -- Move forward with caution.
15 | We recommend using "macro" in place of "forceMacro" method if you do not
16 | need to override pre-existing or base behavior.
17 | `);
18 |
19 | this[name] = fn;
20 | };
21 |
--------------------------------------------------------------------------------
/src/methods/forceMacro.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | /**
5 | * Similar to "macro" function, with ability to forcibly overwrite base prototype methods and existing macro methods
6 | * (See Laravel Macros For In Depth Explanation)
7 | *
8 | * @param name
9 | * @param fn
10 | * @return void
11 | */
12 | module.exports = function forceMacro(name, fn) {
13 | console.warn(`
14 | Forcing macro to implement ${name} method -- Move forward with caution.
15 | We recommend using "macro" in place of "forceMacro" method if you do not
16 | need to override pre-existing or base behavior.
17 | `);
18 |
19 | this[name] = fn;
20 | this.constructor.prototype[name] = fn;
21 | };
22 |
--------------------------------------------------------------------------------
/src/methods/forget.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | const fieldsFrom = require('../helpers/fieldsOf.js');
5 |
6 | module.exports = function forget(...list) {
7 | const fields = fieldsFrom(this, list);
8 |
9 | this.data = fields.isEmpty() ? {} : this.except(...fields.toArray());
10 | };
11 |
--------------------------------------------------------------------------------
/src/methods/has.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const dataGet = require('../helpers/dataGet');
4 | const fieldsOf = require('../helpers/fieldsOf');
5 |
6 | module.exports = function has(...args) {
7 | const value = key => dataGet(this.data, key);
8 |
9 | return fieldsOf(this, args).has().every(value);
10 | };
11 |
--------------------------------------------------------------------------------
/src/methods/hasAny.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const dataGet = require('../helpers/dataGet');
4 | const fieldsOf = require('../helpers/fieldsOf');
5 |
6 | module.exports = function hasAny(...args) {
7 | const value = key => dataGet(this.data, key);
8 |
9 | return fieldsOf(this, args).has().some(value);
10 | };
11 |
--------------------------------------------------------------------------------
/src/methods/input.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const isEmpty = require('../helpers/isEmpty.js');
4 | const dataGet = require('../helpers/dataGet.js');
5 |
6 | module.exports = function input(key, defaultValue = false) {
7 | const value = dataGet(this.data, key);
8 |
9 | return isEmpty(value) ? defaultValue : value;
10 | };
11 |
--------------------------------------------------------------------------------
/src/methods/keys.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function keys() {
4 | return Object.keys(this.data)
5 | };
6 |
--------------------------------------------------------------------------------
/src/methods/localMacro.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | /**
5 | * Add/Extend Form Functionality On Specific Instance With Custom Methods Using LocalMacro
6 | *
7 | * @param name
8 | * @param fn
9 | */
10 | module.exports = function localMacro(name, fn) {
11 | if (typeof this.constructor.prototype[name] !== 'undefined' || typeof this[name] !== 'undefined') {
12 | console.error(`Cant extend form with ${name} localMacro, it already exists (use forceLocalMacro if you want to forcibly overwrite base behavior or previously set macro/localMacro`);
13 | } else {
14 | this[name] = fn;
15 | }
16 | };
17 |
--------------------------------------------------------------------------------
/src/methods/macro.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | /**
5 | * Add/Extend Form Functionality With Custom Methods Using Macros (globally)
6 | *
7 | * @param name
8 | * @param fn
9 | */
10 | module.exports = function macro(name, fn) {
11 | if (Object.keys(this.constructor.prototype).includes(name)) {
12 | return console.error(`Cant extend form with ${name} macro, it already exists (use forceMacro if you want to forcibly overwrite base behavior or previously set macro`);
13 | }
14 | else {
15 | this[name] = fn;
16 | this.constructor.prototype[name] = fn;
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/src/methods/make.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const accessor = require('../helpers/accessor');
4 |
5 | module.exports = function make(input) {
6 | return accessor(new this.constructor(input));
7 | };
8 |
--------------------------------------------------------------------------------
/src/methods/missing.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const exists = require('../helpers/exists');
4 | const dataGet = require('../helpers/dataGet');
5 | const fieldsOf = require('../helpers/fieldsOf');
6 |
7 | module.exports = function missing(...args) {
8 | const missing = key => !exists(dataGet(this.data, key));
9 |
10 | return fieldsOf(this, args).has().some(missing);
11 | };
12 |
--------------------------------------------------------------------------------
/src/methods/only.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const variadic = require('../helpers/variadic');
4 |
5 | module.exports = function only(...args) {
6 | const properties = variadic(args);
7 |
8 | return properties.reduce((only, field) => ({
9 | [field]: this.data[field],
10 | ...only
11 | }), {});
12 | };
13 |
--------------------------------------------------------------------------------
/src/methods/proxy.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const accessor = require('../helpers/accessor.js');
4 |
5 | module.exports = function proxy() {
6 | return accessor(this);
7 | };
8 |
--------------------------------------------------------------------------------
/src/methods/set.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | module.exports = function set(input = {}, value) {
5 | if (typeof value === "undefined") {
6 | Object.entries(input).forEach(([key, value]) => {
7 | this.data[key] = value;
8 | });
9 | } else {
10 | this.data[input] = value;
11 | }
12 | };
13 |
--------------------------------------------------------------------------------
/src/methods/toArray.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function toArray() {
4 | return Object.entries(this.data).map(([key, value]) => ({ key, value }))
5 | };
6 |
--------------------------------------------------------------------------------
/src/methods/use.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Use Validator (vuejs-validators)
5 | *
6 | * @param validatable
7 | * @param options
8 | * @returns {*}
9 | */
10 | module.exports = function use(validatable, options = {}) {
11 | this.setValidator = function (rules = {}, messages = {}, translator = {}) {
12 | this.validatorInstance = validatable(this.data, rules, messages, translator);
13 |
14 | return this;
15 | };
16 |
17 | this.hasValidator = function () {
18 | return typeof this.validatorInstance !== 'undefined';
19 | };
20 |
21 | this.rules = function (rules = {}) {
22 | if (this.validator()) {
23 | this.validator().setRules(rules);
24 | } else {
25 | this.validatorInstance = validatable(this.data, rules);
26 | }
27 |
28 | return this;
29 | };
30 |
31 | this.messages = function (messages = {}, rules = {}) {
32 | if (this.hasValidator()) {
33 | this.validator().setMessages(messages);
34 | } else {
35 | this.validatorInstance = validatable(this.data, rules, messages);
36 | }
37 |
38 | return this;
39 | };
40 |
41 | this.validate = function () {
42 | this.validator().setData(this.data);
43 | this.validator().validate();
44 |
45 | return this;
46 | };
47 |
48 | this.validator = function () {
49 | return this.validatorInstance;
50 | };
51 |
52 | this.errors = function () {
53 | return this.validator().errors();
54 | };
55 |
56 | this.setValidator(options);
57 |
58 | return this;
59 | };
60 |
--------------------------------------------------------------------------------
/src/methods/wrap.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function wrap(key) {
4 | return key.split('.').reverse().reduce((payload, property) => ({
5 | [property]: { ...payload }
6 | }), this.data);
7 | };
8 |
--------------------------------------------------------------------------------
/test/methods/accessor_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const accessor = require('../../src/helpers/accessor.js');
4 |
5 | module.exports = (it, expect, form) => {
6 | it('should return true given the accessor proxy properly accesses form.data[name] value via form[name]', () => {
7 | let example = accessor({ data: { name: 'sam' } });
8 |
9 | expect(example.name).to.eql('sam');
10 | });
11 |
12 | it('should return false given the accessor proxy is not used and form.data[name] value does not equal form[name]', () => {
13 | let example = { data: { name: 'sam' } };
14 |
15 | expect(example.name === 'sam').to.eql(false);
16 | });
17 |
18 | it('should return true for proxy successfully working when adding a form without allowing form.data[name] value access via form[name]', () => {
19 | let example = form({ name: 'sam' });
20 |
21 | expect(example.name).to.eql('sam');
22 | });
23 |
24 | it('should return true for proxy successfully working when adding a form validatable. Allowing form.data[name] value access via form[name]', () => {
25 | const Validator = function (data = {}, rules = {}, messages = {}, translator = {}) {
26 | this.data = data;
27 | this.rules = rules;
28 | this.messages = messages;
29 | this.translator = translator;
30 | };
31 |
32 | const validatable = (data = {}, rules = {}, messages = {}, translator = {}) => (new Validator(data, rules, messages, translator));
33 |
34 | let example = form(validatable, { name: 'sam' });
35 |
36 | expect(example.name).to.eql('sam');
37 | });
38 | };
39 |
40 |
--------------------------------------------------------------------------------
/test/methods/all_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = (it, expect, form) => {
4 | it('should return all form input as an object', () => {
5 | expect(form({ name: 'example', email: 'example@gmail.com' }).all()).to.eql({
6 | name: 'example',
7 | email: 'example@gmail.com'
8 | })
9 | });
10 | };
11 |
--------------------------------------------------------------------------------
/test/methods/anyFilled_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = (it, expect, form) => {
4 | it('should return true when any key has a anyFilled value', () => {
5 | expect(form({ check: 'hey', two: '' }).anyFilled('check', 'two')).to.eql(true);
6 | expect(form({ check: ['hey'], two: [] }).anyFilled('check', 'two')).to.eql(true);
7 | expect(form({ check: { wow: 'hey' }, two: '' }).anyFilled('check', 'two')).to.eql(true);
8 | });
9 |
10 | it('should return false when no key has a anyFilled value', () => {
11 | expect(form({ check: '', checkTwo: '' }).anyFilled('check', 'checkTwo')).to.eql(false);
12 | });
13 |
14 | it('should return true when all keys have a anyFilled value', () => {
15 | expect(form({ check: 'fill', checkTwo: 'value' }).anyFilled('check', 'checkTwo')).to.eql(true);
16 | });
17 |
18 | it('should return false when single key does not have a anyFilled value', () => {
19 | expect(form({ check: '' }).anyFilled('check')).to.eql(false);
20 | });
21 |
22 | it('should return true when wild card is used to find key', () => {
23 | expect(form({ tags: [ { name: 'one' }, { name: 'two' } ] }).anyFilled('tags.*.name')).to.eql(true);
24 | });
25 |
26 | it('should return false when wild card is used to find key', () => {
27 | expect(form({ tags: { list: [], category: 'example' } }).anyFilled('tags.list.*')).to.eql(false);
28 | });
29 |
30 | it('should check all values when no arguments are provided', () => {
31 | expect(form({ one: '', two: '', three: '' }).anyFilled()).to.eql(false);
32 | expect(form({ one: 'first', two: '', three: '' }).anyFilled()).to.eql(true);
33 | expect(form({ one: '', two: ['second'], three: '' }).anyFilled()).to.eql(true);
34 | expect(form({ one: '', two: '', three: { third: 'test' } }).anyFilled()).to.eql(true);
35 | });
36 | };
37 |
--------------------------------------------------------------------------------
/test/methods/boolean_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = (it, expect, form) => {
4 | it('should return true for truthy values(true, "true", "yes", "on", 1, and "1")', () => {
5 | expect(form({ check: true }).boolean('check')).to.eql(true);
6 | expect(form({ check: 'true' }).boolean('check')).to.eql(true);
7 | expect(form({ check: 'yes' }).boolean('check')).to.eql(true);
8 | expect(form({ check: 'on' }).boolean('check')).to.eql(true);
9 | expect(form({ check: 1 }).boolean('check')).to.eql(true);
10 | expect(form({ check: '1' }).boolean('check')).to.eql(true);
11 | });
12 |
13 | it('should return false for not truthy values(true, "true", "yes", "on", 1, and "1")', () => {
14 | expect(form({ check: false }).boolean('check')).to.eql(false);
15 | expect(form({ check: 'random' }).boolean('check')).to.eql(false);
16 | expect(form({ check: 0 }).boolean('check')).to.eql(false);
17 | expect(form({ check: [] }).boolean('check.0')).to.eql(false);
18 | expect(form({}).boolean('check')).to.eql(false);
19 | });
20 | };
21 |
--------------------------------------------------------------------------------
/test/methods/empty_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = (it, expect, form) => {
4 | it('should return true when string, array, or object is empty', () => {
5 | expect(form({ one: '', two: [], three: {} }).empty('one', 'two', 'three')).to.eql(true);
6 | });
7 |
8 | it('should return true when some are filled but an empty exists', () => {
9 | expect(form({ one: '', two: 'hey', three: 'world' }).empty('one', 'two', 'three')).to.eql(true);
10 | });
11 |
12 | it('should return true when string, array, or object are empty', () => {
13 | expect(form({ one: 'hey', two: [], three: {} }).empty('one', 'two', 'three')).to.eql(true);
14 | expect(form({ one: '', two: ['yo'], three: {} }).empty('one', 'two', 'three')).to.eql(true);
15 | expect(form({ one: '', two: [], three: { hi: 'world' } }).empty('one', 'two', 'three')).to.eql(true);
16 | });
17 |
18 | it('should return false when string, array, or object are filled', () => {
19 | expect(form({ one: 'hey' }).empty('one')).to.eql(false);
20 | expect(form({ two: ['yo'] }).empty('two')).to.eql(false);
21 | expect(form({ three: { hi: 'world' } }).empty('three')).to.eql(false);
22 | });
23 |
24 | it('should check all values when no arguments are provided', () => {
25 | expect(form({ one: '', two: '', three: '' }).empty()).to.eql(true);
26 | expect(form({ one: 'first', two: '', three: '' }).empty()).to.eql(true);
27 | expect(form({ one: '', two: ['second'], three: '' }).empty()).to.eql(true);
28 | expect(form({ one: '', two: '', three: { third: 'test' } }).empty()).to.eql(true);
29 | expect(form({ one: 'first', two: ['second'], three: { third: 'test' } }).empty()).to.eql(false);
30 | });
31 | };
32 |
--------------------------------------------------------------------------------
/test/methods/except_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = (it, expect, form) => {
4 | it('should return all except the key/values where the pairs key lines up with the passed in keys', () => {
5 | expect(form({ name: 'example', email: 'example@gmail.com' }).except('name')).to.eql({
6 | email: 'example@gmail.com'
7 | });
8 |
9 | expect(form({ id: 1, name: 'example', email: 'example@gmail.com' })
10 | .except('name', 'email')).to.eql({ id: 1 });
11 | })
12 | };
13 |
--------------------------------------------------------------------------------
/test/methods/fill_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = (it, expect, form) => {
4 | it('should fill in input data but not override previous non empty data', () => {
5 | const example = form({ id: null, email: 'example@gmail.com' });
6 |
7 | expect(example.all()).to.eql({ id: null, email: 'example@gmail.com' });
8 |
9 | example.fill({ id: 1, email: 'hey@g.com' });
10 |
11 | expect(example.all()).to.eql({ id: 1, email: 'example@gmail.com' });
12 | });
13 | };
14 |
--------------------------------------------------------------------------------
/test/methods/filled_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = (it, expect, form) => {
4 | it('should return true when key has a filled value', () => {
5 | expect(form({ check: 'hey' }).filled('check')).to.eql(true);
6 | expect(form({ check: ['hey'] }).filled('check')).to.eql(true);
7 | expect(form({ check: { wow: 'hey' } }).filled('check')).to.eql(true);
8 | });
9 |
10 | it('should return false when any key does not have a filled value', () => {
11 | expect(form({ check: '', checkTwo: 'value' }).filled('check', 'checkTwo')).to.eql(false);
12 | });
13 |
14 | it('should return true when all keys have a filled value', () => {
15 | expect(form({ check: 'fill', checkTwo: 'value' }).filled('check', 'checkTwo')).to.eql(true);
16 | });
17 | it('should return false when single key does not have a filled value', () => {
18 | expect(form({ check: '' }).filled('check')).to.eql(false);
19 | });
20 |
21 | it('should check all are filled when no arguments are provided', () => {
22 | expect(form({ one: '', two: '', three: '' }).filled()).to.eql(false);
23 | expect(form({ one: 'first', two: '', three: '' }).filled()).to.eql(false);
24 | expect(form({ one: '', two: ['second'], three: '' }).filled()).to.eql(false);
25 | expect(form({ one: '', two: '', three: { third: 'test' } }).filled()).to.eql(false);
26 | expect(form({ one: 'first', two: ['second'], three: { third: 'test' } }).filled()).to.eql(true);
27 | });
28 | };
29 |
--------------------------------------------------------------------------------
/test/methods/forceLocal_macro.test.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | module.exports = (it, expect, form) => {
5 | it('should be able to extend the instance of form prototype using "forceLocalMacro"', () => {
6 | let example = form();
7 | expect(Object.keys(example).includes('example_force_macro_method')).to.eql(false);
8 |
9 | example.forceLocalMacro('example_force_local_macro', function () {
10 | return 'hello world';
11 | });
12 |
13 | expect(example.example_force_local_macro()).to.eql('hello world');
14 | expect(typeof form({}).example_force_local_macro === 'undefined').to.eql(true);
15 | });
16 |
17 | it('should be able to forcibly overwrite a base form prototype function using "forceMacro"', () => {
18 |
19 | let example = form({ name: 'sam' });
20 | expect(example.all()).to.eql({ name: 'sam' });
21 |
22 | example.forceLocalMacro('all', function () {
23 | return 'hello world';
24 | });
25 |
26 | expect(example.all()).to.eql('hello world');
27 | expect(form({ name: 'sam' }).all()).to.eql({ name: 'sam' });
28 | });
29 |
30 | it('should be able to forcibly overwrite a previously defined "macro"', () => {
31 | let example = form({ name: 'sam' });
32 |
33 | example.localMacro('inspire', function () {
34 | return `We believe in you ${this.data.name}`;
35 | });
36 |
37 | expect(example.inspire()).to.eql("We believe in you sam");
38 |
39 | example.forceLocalMacro('inspire', function () {
40 | return `We have faith in you sarah`
41 | });
42 |
43 | expect(example.inspire()).to.eql("We have faith in you sarah");
44 | });
45 |
46 | };
47 |
--------------------------------------------------------------------------------
/test/methods/forceMacro_test.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | module.exports = (it, expect, form) => {
5 | it('should be able to extend the base form prototype using "forceMacro"', () => {
6 | expect(Object.keys(form).includes('example_force_macro_method')).to.eql(false);
7 |
8 | form().forceMacro('example_force_macro_method', function () {
9 | return 'hello world';
10 | });
11 |
12 | expect(form().example_force_macro_method()).to.eql('hello world');
13 | });
14 |
15 | it('should be able to forcibly overwrite a base form prototype function using "forceMacro"', () => {
16 |
17 | expect(form({ name: 'sam' }).all()).to.eql({ name: 'sam' });
18 |
19 | form().forceMacro('all', function () {
20 | return 'hello world';
21 | });
22 |
23 | expect(form({ name: 'sam' }).all()).to.eql('hello world');
24 |
25 | form().forceMacro('all', function () {
26 | return this.data;
27 | });
28 |
29 | expect(form({ name: 'sam' }).all()).to.eql({ name: 'sam' });
30 | });
31 |
32 | it('should be able to forcibly overwrite a previously defined "macro"', () => {
33 | let example = form({ name: 'sam' });
34 |
35 | form().macro('inspire', function () {
36 | return `We believe in you ${this.data.name}`;
37 | });
38 |
39 | expect(example.inspire()).to.eql("We believe in you sam");
40 |
41 | form().forceMacro('inspire', function () {
42 | return `We have faith in you sarah`
43 | });
44 |
45 | expect(example.inspire()).to.eql("We have faith in you sarah");
46 |
47 | });
48 |
49 | form().forceMacro('all', function () {
50 | return this.data;
51 | });
52 | };
53 |
--------------------------------------------------------------------------------
/test/methods/forget_test.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | module.exports = (it, expect, form) => {
5 | it('should forget an input key value pair properly', () => {
6 | const example = form({ name: 'example', email: 'example@gmail.com' });
7 |
8 | expect(example.all()).to.eql({ name: 'example', email: 'example@gmail.com' });
9 |
10 | example.forget('name');
11 |
12 | expect(example.all()).to.eql({ email: 'example@gmail.com' });
13 | });
14 |
15 | it('should forget multiple input key value pair properly', () => {
16 | const example = form({ id: 1, name: 'example', email: 'example@gmail.com' });
17 |
18 | expect(example.all()).to.eql({ id: 1, name: 'example', email: 'example@gmail.com' });
19 |
20 | example.forget('name', 'id');
21 |
22 | expect(example.all()).to.eql({ email: 'example@gmail.com' });
23 | });
24 |
25 | it('should forget all input when no parameters are passed', () => {
26 | const example = form({ id: 1, name: 'example', email: 'example@gmail.com' });
27 |
28 | expect(example.all()).to.eql({ id: 1, name: 'example', email: 'example@gmail.com' });
29 |
30 | example.forget();
31 |
32 | expect(example.all()).to.eql({});
33 | });
34 | };
35 |
--------------------------------------------------------------------------------
/test/methods/hasAny_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = (it, expect, form) => {
4 | it('should return true if it has any of the given keys', () => {
5 | expect(form({ name: 'example', email: 'example@gmail.com' }).hasAny('name', 'missing')).to.eql(true)
6 | });
7 |
8 | it('should return false if its missing all of the given keys', () => {
9 | expect(form({ name: 'example', email: 'example@gmail.com' }).hasAny('something', 'missing')).to.eql(false)
10 | });
11 |
12 | it('should return true or false based on values existing within wild card paths', () => {
13 | expect(form({ post: {
14 | meta: { tags: ['one', 'two', 'three'] },
15 | }}).hasAny('post.meta.tags', 'something')).to.eql(true);
16 |
17 | expect(form({ post: { meta: { }, }}).hasAny('post.meta.tags')).to.eql(false)
18 | });
19 | };
20 |
--------------------------------------------------------------------------------
/test/methods/has_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = (it, expect, form) => {
4 | it('should return true if it has the given keys', () => {
5 | expect(form({ name: 'example', email: 'example@gmail.com' }).has('name', 'email')).to.eql(true)
6 | });
7 |
8 | it('should return false if it does not have any of the given keys', () => {
9 | expect(form({ name: 'example', email: 'example@gmail.com' }).has('name', 'email', 'missing')).to.eql(false)
10 | });
11 |
12 | it('should return true or false based on values existing within wild card paths', () => {
13 | expect(form({ post: {
14 | meta: { tags: ['one', 'two', 'three'] },
15 | }}).has('post.meta.tags')).to.eql(true);
16 |
17 | expect(form({ post: { meta: { }, }}).has('post.meta.tags')).to.eql(false)
18 | });
19 | };
20 |
--------------------------------------------------------------------------------
/test/methods/input_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = (it, expect, form) => {
4 | it('should except a key and then return the value, if its missing then return the default, if there is no default then return false', () => {
5 | expect(form({ name: 'example', email: 'example@gmail.com' }).input('name')).to.eql('example');
6 | expect(form({ name: 'example', email: 'example@gmail.com' }).input('something', 'default')).to.eql('default');
7 | expect(form({ name: 'example', email: 'example@gmail.com' }).input('something')).to.eql(false);
8 | });
9 |
10 | it('accept a key with a wildcard and be able to use the default value if the given value is empty', () => {
11 | expect(form({ name: 'example', email: 'example@gmail.com' }).input('something', 'default')).to.eql('default');
12 | expect(form({ name: 'example', email: 'example@gmail.com' }).input('something')).to.eql(false);
13 |
14 | expect(form({ family: {
15 | mom: { name: 'julie' }, dad: { name: 'rob' }
16 | }
17 | }).input('family.*.name')).to.eql(['julie', 'rob']);
18 |
19 | expect(form({ family: {
20 | mom: { name: 'julie' }, dad: { name: 'rob' }
21 | }
22 | }).input('family.*.email', ['julie@gmail.com', 'rob@gmail.com'])).to.eql(['julie@gmail.com', 'rob@gmail.com']);
23 | });
24 |
25 |
26 | };
27 |
--------------------------------------------------------------------------------
/test/methods/keys_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = (it, expect, form) => {
4 | it('should return an array of the input keys', () => {
5 | expect(form({ name: 'example', email: 'example@gmail.com' }).keys()).to.eql(['name', 'email'])
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/test/methods/localMacro_test.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | module.exports = (it, expect, form) => {
5 | it('should be able to extend the base form prototype using a "macro"', () => {
6 | expect(typeof form({ email: 'e@g.com' }).example_local_macro_method === 'undefined').to.eql(true);
7 |
8 | form().macro('example_local_macro_method', function () {
9 | return 'hello world';
10 | });
11 |
12 | expect(typeof form({ email: 'e@g.com'}).example_local_macro_method === 'undefined').to.eql(false);
13 | expect(form().example_local_macro_method()).to.eql('hello world');
14 | });
15 |
16 | it('should not be able to forcibly overwrite a base form prototype function using a "macro"', () => {
17 | expect(form({ name: 'sam' }).all()).to.eql({ name: 'sam' });
18 |
19 | form().macro('all', function () {
20 | return 'hello world';
21 | });
22 |
23 | expect(form({ name: 'sam' }).all()).to.eql({ name: 'sam' });
24 | });
25 |
26 | it('should not apply localMacro everywhere', () => {
27 | form().localMacro('everywhere', () => 'world');
28 |
29 | let one = form({ first: 'test' });
30 | let two = form({ second: 'test' });
31 |
32 | expect(typeof one.everywhere === 'undefined').to.eql(true);
33 | expect(typeof two.everywhere === 'undefined').to.eql(true);
34 |
35 | one.localMacro('everywhere', () => 'world');
36 |
37 | expect(one.everywhere()).to.eql('world');
38 | expect(typeof two.everywhere === 'undefined').to.eql(true);
39 | });
40 |
41 | it('should allow macros to be applied on a specific instance instead of everywhere', () => {
42 | let does_have = form({ first: 'first' });
43 | let does_not_have = form({ second: 'test' });
44 |
45 | does_have.localMacro('localized', () => 'success');
46 |
47 | expect(typeof does_have.localized === 'undefined').to.eql(false);
48 | expect(typeof does_not_have.localized === 'undefined').to.eql(true);
49 | });
50 | };
51 |
--------------------------------------------------------------------------------
/test/methods/macro_test.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | module.exports = (it, expect, form) => {
5 | it('should be able to extend base prototype using a "macro"', () => {
6 | expect(typeof form().example_macro_method === 'undefined').to.eql(true);
7 |
8 | form({}).macro('example_macro_method', function () {
9 | return 'hello world';
10 | });
11 |
12 | expect(typeof form({}).example_macro_method === 'undefined').to.eql(false);
13 |
14 | expect(form({}).example_macro_method()).to.eql('hello world');
15 | });
16 |
17 | it('should not be able to force overwrite on form prototype function using a "macro"', () => {
18 | expect(form({ name: 'sam' }).all()).to.eql({ name: 'sam' });
19 |
20 | form().macro('all', function () {
21 | return 'hello world';
22 | });
23 |
24 | expect(form({ name: 'sam' }).all()).to.eql({ name: 'sam' });
25 | });
26 |
27 | it('should apply macros everywhere or on every prototype instance created by default', () => {
28 | form().macro('macro_everywhere', () => 'world');
29 |
30 | let one = form({ first: 'test' });
31 | let two = form({ second: 'test' });
32 |
33 | expect(one.macro_everywhere()).to.eql('world');
34 | expect(two.macro_everywhere()).to.eql('world');
35 |
36 | });
37 | };
38 |
--------------------------------------------------------------------------------
/test/methods/missing_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = (it, expect, form) => {
4 | it('should be true if it is missing from the input', () => {
5 | expect(form({ name: 'example', email: 'example@gmail.com' }).missing('something')).to.eql(true)
6 | });
7 | it('should be false if it is not missing from the input (even if empty)', () => {
8 | expect(form({ name: 'example', email: '' }).missing('email')).to.eql(false)
9 | });
10 | it('should be true if any are missing from the input', () => {
11 | expect(form({ name: 'example', email: '' }).missing('email', 'something')).to.eql(true)
12 | });
13 | it('should be false if all are in the input', () => {
14 | expect(form({ name: 'example', email: '' }).missing('name', 'email')).to.eql(false)
15 | })
16 | };
17 |
--------------------------------------------------------------------------------
/test/methods/only_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = (it, expect, form) => {
4 | it('should return only the key/values where the pairs line up with the passed in keys', () => {
5 | expect(form({ name: 'example', email: 'example@gmail.com' }).only('email')).to.eql({
6 | email: 'example@gmail.com'
7 | });
8 |
9 | expect(form({ id: 1, name: 'example', email: 'example@gmail.com' }).only('id', 'email')).to.eql({
10 | id: 1, email: 'example@gmail.com'
11 | });
12 | })
13 | };
14 |
--------------------------------------------------------------------------------
/test/methods/set_test.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | module.exports = (it, expect, form) => {
5 | it('should set input data and override previous non empty data', () => {
6 | const example = form({ id: null, email: 'example@gmail.com' });
7 |
8 | expect(example.all()).to.eql({ id: null, email: 'example@gmail.com' });
9 |
10 | example.set({ id: 1, email: 'hey@g.com' });
11 |
12 | expect(example.all()).to.eql({ id: 1, email: 'hey@g.com' });
13 | });
14 | };
15 |
--------------------------------------------------------------------------------
/test/methods/toArray_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = (it, expect, form) => {
4 | it('should return an array of key value pair objects', () => {
5 | expect(form({ name: 'example', email: 'example@gmail.com' }).toArray()).to.eql(
6 | [
7 | { key: 'name', value: 'example' },
8 | { key: 'email', value: 'example@gmail.com' }
9 | ]
10 | )
11 | });
12 | };
13 |
--------------------------------------------------------------------------------
/test/methods/use_test.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = (it, expect, form) => {
3 | const Validator = function (data, rules, messages, translator) {
4 | this.data = data;
5 | this.rules = rules;
6 | this.confirm = 'success';
7 | this.messages = messages;
8 | this.translator = translator;
9 | this.errorBag = {
10 | data: {
11 | a: ['one', 'two'],
12 | b: ['three']
13 | },
14 | };
15 |
16 | this.errorBag.all = () => this.errorBag.data;
17 | this.errorBag.list = () => ['one', 'two', 'three'];
18 | };
19 |
20 | Validator.prototype.validate = function () {
21 | this.errorBag.data = {
22 | one: ['a', 'b', 'c', 'd'],
23 | two: ['e', 'f', 'g', 'h']
24 | };
25 |
26 | this.errorBag.all = () => this.errorBag.data;
27 | this.errorBag.list = () => ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
28 |
29 | return this;
30 | };
31 |
32 | Validator.prototype.errors = function () {
33 | return this.errorBag;
34 | };
35 |
36 | Validator.prototype.setRules = function (rules) {
37 | this.rules = rules;
38 |
39 | return this;
40 | };
41 |
42 | Validator.prototype.setMessages = function (messages) {
43 | this.messages = messages;
44 |
45 | return this;
46 | };
47 |
48 | Validator.prototype.setData = function (data) {
49 | this.data = data;
50 |
51 | return this;
52 | };
53 |
54 | const validatable = (data = {}, rules = {}, messages = {}, translator = {}) => (new Validator(data, rules, messages, translator));
55 |
56 | it('should "use" validatable instance and be able to get "validator"', () => {
57 | let example = form(validatable, { name: 'sam' });
58 |
59 | expect(example.validator().data).to.eql({ name: 'sam' });
60 | });
61 |
62 | it('should "use" validatable instance and confirm it "hasValidator"', () => {
63 | let example = form(validatable, { name: 'sam' });
64 |
65 | expect(example.hasValidator()).to.eql(true);
66 | });
67 |
68 | it('should "use" validatable and set "rules"', () => {
69 | let example = form(validatable, { name: 'sam' }).rules({
70 | 'name': 'required|min:4'
71 | });
72 |
73 | expect(example.validator().rules).to.eql({ 'name': 'required|min:4' });
74 | });
75 |
76 | it('should "use" validatable and set "messages"', () => {
77 | let example = form(validatable, { name: 'sam' }).rules({
78 | 'name': 'required|min:4'
79 | }).messages({
80 | 'name.required': 'name is required',
81 | 'name.min': 'name must not be less than :min characters'
82 | });
83 |
84 | expect(example.validator().messages).to.eql({
85 | 'name.required': 'name is required',
86 | 'name.min': 'name must not be less than :min characters'
87 | });
88 | });
89 |
90 | it('should "use" validatable, with ability to "validate" and get "errors"', () => {
91 | let example = form(validatable, { name: 'sam' }).rules({
92 | 'name': 'required|min:4'
93 | }).messages({
94 | 'name.required': 'name is required',
95 | 'name.min': 'name must not be less than :min characters'
96 | });
97 |
98 | expect(example.validate().errors().list()).to.eql([
99 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'
100 | ]);
101 | });
102 |
103 | it('should "use" validatable, with ability to "setValidator" a new', () => {
104 | let example = form(validatable, { name: 'sam' }).rules({
105 | 'name': 'required|min:4'
106 | }).messages({
107 | 'name.required': 'name is required',
108 | 'name.min': 'name must not be less than :min characters'
109 | });
110 |
111 | example.setValidator({
112 | 'name': 'required',
113 | }, {
114 | 'name.required': 'Updated Messages'
115 | }, {
116 | 'phrases': 'cool'
117 | });
118 |
119 | expect(example.validator().rules).to.eql({
120 | 'name': 'required',
121 | });
122 |
123 | expect(example.validator().messages).to.eql({
124 | 'name.required': 'Updated Messages'
125 | });
126 |
127 | expect(example.validator().translator).to.eql({
128 | 'phrases': 'cool'
129 | });
130 | });
131 | };
132 |
--------------------------------------------------------------------------------
/test/methods/wrap_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = (it, expect, form) => {
4 | it('should return data object wrapped or nested under the wrapped property key', () => {
5 | expect(form({ name: 'example', email: 'example@gmail.com' }).wrap('data')).to.eql({
6 | data: { name: 'example', email: 'example@gmail.com' }
7 | })
8 | });
9 |
10 | it('should return data object wrapped or nested under nested property keys', () => {
11 | expect(form({ name: 'example', email: 'example@gmail.com' }).wrap('data.user.personal')).to.eql({
12 | data: {
13 | user: {
14 | personal: {
15 | name: 'example',
16 | email: 'example@gmail.com'
17 | }
18 | }
19 | }
20 | })
21 | });
22 | };
23 |
--------------------------------------------------------------------------------
/test/tests.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 | const { it } = require('mocha');
5 | const { describe } = require('mocha');
6 | const path = require('path');
7 | const { expect } = require('chai');
8 | const { SimpleForm: form } = require('../dist');
9 |
10 | let test = process.argv[process.argv.length - 1];
11 | const runSingleTest = test.indexOf('--') !== -1;
12 | test = test.replace('--', '');
13 | test += '_test.js';
14 |
15 | const tests = fs.readdirSync(path.join(__dirname, 'methods'));
16 | const methods = fs.readdirSync(path.join(__dirname, '../src/methods'));
17 |
18 | tests.forEach((file) => {
19 | describe(file.replace('_test.js', '()'), () => {
20 | if (!runSingleTest) {
21 | // eslint-disable-next-line
22 | require(path.join(__dirname, 'methods', file))(it, expect, form);
23 | } else if (runSingleTest && file === test) {
24 | // eslint-disable-next-line
25 | require(path.join(__dirname, 'methods', file))(it, expect, form);
26 | }
27 | });
28 | });
29 |
30 | // if (!runSingleTest) {
31 | // describe('general tests', () => {
32 | // it('should test every method', () => {
33 | // const missingTests = collect(methods).diff(collect(tests).transform(t => t.replace(/_test/, ''))).all();
34 | // expect(missingTests).to.eql([]);
35 | // });
36 |
37 | // it('should document all methods in README.md', () => {
38 | // const content = fs.readFileSync(path.join(__dirname, '../README.md'), 'utf-8');
39 |
40 | // const re = /#### `(.*)\(\)`/g;
41 | // let matches = re.exec(content);
42 |
43 | // const documentedMethods = [];
44 |
45 | // while (matches !== null) {
46 | // documentedMethods.push(matches[1]);
47 | // matches = re.exec(content);
48 | // }
49 |
50 | // const missingDocumentation = collect(methods).transform(t => t.replace(/.js/, '')).diff(documentedMethods).all();
51 | // expect(missingDocumentation).to.eql(['symbol.iterator']);
52 | // });
53 |
54 | // it('should document all methods in docs/api', () => {
55 | // const docFiles = fs.readdirSync(path.join(__dirname, '../docs/api'), 'utf-8');
56 | // const methodFiles = fs.readdirSync(path.join(__dirname, '../src/methods'), 'utf-8');
57 |
58 | // const docsCollection = collect(docFiles).map(t => t.replace(/.md/, ''));
59 | // const methodsCollection = collect(methodFiles).map(t => t.replace(/.js/, ''));
60 |
61 | // expect(methodsCollection.diff(docsCollection).all()).to.eql(['symbol.iterator']);
62 | // });
63 |
64 | // it('should not have any dependencies', () => {
65 | // const content = fs.readFileSync('package.json');
66 | // const pckg = JSON.parse(content);
67 |
68 | // expect(pckg.dependencies).to.eql(undefined);
69 | // });
70 | // });
71 |
--------------------------------------------------------------------------------