Compare commits
30 commits
Author | SHA1 | Date | |
---|---|---|---|
|
a4375f0a22 | ||
|
119286a524 | ||
|
cbe80e3de4 | ||
|
bfeba566d9 | ||
|
eda7a1d79d | ||
|
12235e8307 | ||
|
92a3f8cc60 | ||
|
497b2a1967 | ||
|
fa4bc2683c | ||
|
b83a429117 | ||
|
0d2a5329db | ||
|
dfc6557bc6 | ||
|
6224b40e02 | ||
|
1e456627a1 | ||
|
f204f9b672 | ||
|
0b20bbbd95 | ||
|
8c1e979871 | ||
|
90f2439692 | ||
|
78b1ac6da5 | ||
|
877a672ce9 | ||
|
593af7efc8 | ||
|
674449707b | ||
|
e3e7aea10d | ||
|
b3849e45f3 | ||
|
0b5607bbbe | ||
|
2f3a63b012 | ||
|
da56b04213 | ||
|
76dec48d64 | ||
|
29975e3ddb | ||
|
67dba981a1 |
34 changed files with 2673 additions and 4365 deletions
35
.eslintrc.js
35
.eslintrc.js
|
@ -1,30 +1,27 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
|
|
||||||
parserOptions: {
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
sourceType: 'module',
|
|
||||||
},
|
|
||||||
|
|
||||||
plugins: ['@typescript-eslint'],
|
|
||||||
|
|
||||||
// https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
|
|
||||||
extends: [
|
|
||||||
'standard',
|
|
||||||
'@vue/standard',
|
|
||||||
'@vue/typescript',
|
|
||||||
'plugin:@typescript-eslint/recommended',
|
|
||||||
'plugin:vue/recommended',
|
|
||||||
],
|
|
||||||
|
|
||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
parserOptions: {
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
'@typescript-eslint',
|
||||||
|
'vue',
|
||||||
|
],
|
||||||
|
|
||||||
|
// https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
|
||||||
|
extends: [
|
||||||
|
'plugin:@typescript-eslint/eslint-recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'plugin:vue/recommended',
|
||||||
|
],
|
||||||
|
|
||||||
rules: {
|
rules: {
|
||||||
'@typescript-eslint/camelcase': ['error', {
|
|
||||||
allow: ['^__Formulario'],
|
|
||||||
}],
|
|
||||||
'@typescript-eslint/no-empty-function': 'off',
|
'@typescript-eslint/no-empty-function': 'off',
|
||||||
'@typescript-eslint/no-explicit-any': 'off', // @TODO
|
'@typescript-eslint/no-explicit-any': 'off', // @TODO
|
||||||
'@typescript-eslint/no-unused-vars': ['error'], // @TODO
|
'@typescript-eslint/no-unused-vars': ['error'], // @TODO
|
||||||
|
|
11
.gitignore
vendored
11
.gitignore
vendored
|
@ -1,11 +1,16 @@
|
||||||
node_modules
|
|
||||||
coverage
|
|
||||||
.cache
|
.cache
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
|
coverage
|
||||||
|
dist/
|
||||||
|
node_modules
|
||||||
|
|
||||||
*.sublime-project
|
*.sublime-project
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
*.dev.tale.vue
|
*.dev.tale.vue
|
||||||
*.dev.stories.js
|
*.dev.stories.js
|
||||||
storybook-static
|
|
||||||
|
storybook-static
|
||||||
|
.npmrc
|
||||||
|
|
49
CHANGELOG.md
49
CHANGELOG.md
|
@ -2,6 +2,55 @@
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||||
|
|
||||||
|
### [0.8.3](https://github.com/retailcrm/vue-formulario/compare/v0.8.2...v0.8.3) (2024-12-06)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Updated package.json manifest ([cbe80e3](https://github.com/retailcrm/vue-formulario/commit/cbe80e3de498732af8db34f0846cc92d977d9420))
|
||||||
|
|
||||||
|
### [0.8.2](https://github.com/retailcrm/vue-formulario/compare/v0.8.1...v0.8.2) (2023-12-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Added web-types declaration ([eda7a1d](https://github.com/retailcrm/vue-formulario/commit/eda7a1d79d98e4ccd76e67bc93c1bf8dc5249e67))
|
||||||
|
|
||||||
|
### [0.8.1](https://github.com/retailcrm/vue-formulario/compare/v0.8.0...v0.8.1) (2023-12-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* build ([92a3f8c](https://github.com/retailcrm/vue-formulario/commit/92a3f8cc60fdfb1f7588b281febcc833b17d3521))
|
||||||
|
|
||||||
|
## [0.8.0](https://github.com/retailcrm/vue-formulario/compare/v0.7.3...v0.8.0) (2023-12-28)
|
||||||
|
|
||||||
|
|
||||||
|
### ⚠ BREAKING CHANGES
|
||||||
|
|
||||||
|
* Old names of FormularioField & FormularioFieldGroup no longer available
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Components conststructors are exposed as external API, added TypeScript declarations ([dfc6557](https://github.com/retailcrm/vue-formulario/commit/dfc6557bc632489daeb8f4ae44ad208f6c6a9997))
|
||||||
|
|
||||||
|
|
||||||
|
* Old names of FormularioField & FormularioFieldGroup no longer available ([b83a429](https://github.com/retailcrm/vue-formulario/commit/b83a42911749272c9c8bd35c4ea10f687c5d8821))
|
||||||
|
|
||||||
|
### [0.7.3](https://github.com/retailcrm/vue-formulario/compare/v0.7.2...v0.7.3) (2021-11-11)
|
||||||
|
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Fixed toString calls in validators ([da56b04](https://github.com/retailcrm/vue-formulario/commit/da56b04213b6ebc3d001a273b26a350a59e0382b))
|
||||||
|
|
||||||
|
### [0.7.2](https://github.com/retailcrm/vue-formulario/compare/v0.7.1...v0.7.2) (2021-10-21)
|
||||||
|
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Blob objects are no longer cloned ([67dba98](https://github.com/retailcrm/vue-formulario/commit/67dba981a15b04a84512de277f633d0f7d19d543))
|
||||||
|
|
||||||
### [0.7.1](https://github.com/retailcrm/vue-formulario/compare/v0.7.0...v0.7.1) (2021-09-30)
|
### [0.7.1](https://github.com/retailcrm/vue-formulario/compare/v0.7.0...v0.7.1) (2021-09-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,7 @@ export default {
|
||||||
input: 'src/index.ts',
|
input: 'src/index.ts',
|
||||||
output: [{
|
output: [{
|
||||||
name: 'Formulario',
|
name: 'Formulario',
|
||||||
exports: 'default',
|
|
||||||
globals: {
|
globals: {
|
||||||
'is-plain-object': 'isPlainObject',
|
|
||||||
'is-url': 'isUrl',
|
'is-url': 'isUrl',
|
||||||
vue: 'Vue',
|
vue: 'Vue',
|
||||||
'vue-property-decorator': 'vuePropertyDecorator',
|
'vue-property-decorator': 'vuePropertyDecorator',
|
||||||
|
|
|
@ -11,10 +11,8 @@ export default {
|
||||||
input: 'src/index.ts',
|
input: 'src/index.ts',
|
||||||
output: {
|
output: {
|
||||||
name: 'VueFormulario',
|
name: 'VueFormulario',
|
||||||
exports: 'default',
|
|
||||||
format: 'iife',
|
format: 'iife',
|
||||||
globals: {
|
globals: {
|
||||||
'is-plain-object': 'isPlainObject',
|
|
||||||
'is-url': 'isUrl',
|
'is-url': 'isUrl',
|
||||||
vue: 'Vue',
|
vue: 'Vue',
|
||||||
'vue-property-decorator': 'vuePropertyDecorator',
|
'vue-property-decorator': 'vuePropertyDecorator',
|
||||||
|
@ -30,7 +28,7 @@ export default {
|
||||||
vue({ css: true, compileTemplate: true }),
|
vue({ css: true, compileTemplate: true }),
|
||||||
alias({ entries: [{ find: /^@\/(.+)/, replacement: './$1' }] }),
|
alias({ entries: [{ find: /^@\/(.+)/, replacement: './$1' }] }),
|
||||||
commonjs(),
|
commonjs(),
|
||||||
internal(['is-plain-object', 'is-url', 'vue-property-decorator']),
|
internal(['is-url', 'vue-property-decorator']),
|
||||||
terser(),
|
terser(),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
1544
dist/formulario.esm.js
vendored
1544
dist/formulario.esm.js
vendored
File diff suppressed because it is too large
Load diff
34
dist/formulario.min.js
vendored
34
dist/formulario.min.js
vendored
File diff suppressed because one or more lines are too long
1551
dist/formulario.umd.js
vendored
1551
dist/formulario.umd.js
vendored
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
||||||
version: '3.6'
|
version: '3.6'
|
||||||
services:
|
services:
|
||||||
node:
|
node:
|
||||||
image: node:12-alpine
|
image: node:16-alpine
|
||||||
user: node
|
user: node
|
||||||
volumes:
|
volumes:
|
||||||
- ./:/var/www/vue-formulario
|
- ./:/var/www/vue-formulario
|
||||||
|
|
94
index.d.ts
vendored
Normal file
94
index.d.ts
vendored
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
// noinspection JSUnusedGlobalSymbols
|
||||||
|
|
||||||
|
import type { Vue } from 'vue/types/vue'
|
||||||
|
import type { PluginObject } from 'vue/types/plugin'
|
||||||
|
|
||||||
|
import type { DefineComponent } from './types/vue'
|
||||||
|
|
||||||
|
import type { FormularioFormConstructor } from './types/form'
|
||||||
|
|
||||||
|
import type {
|
||||||
|
ModelGetConverter,
|
||||||
|
ModelSetConverter,
|
||||||
|
ValidationBehaviour,
|
||||||
|
UnregisterBehaviour,
|
||||||
|
} from './types/field'
|
||||||
|
|
||||||
|
import type {
|
||||||
|
ValidationMessageFn,
|
||||||
|
ValidationMessageI18NFn,
|
||||||
|
ValidationRuleFn,
|
||||||
|
Violation,
|
||||||
|
} from './types/validation'
|
||||||
|
|
||||||
|
import type { Options } from './types/plugin'
|
||||||
|
|
||||||
|
declare const FormularioForm: FormularioFormConstructor
|
||||||
|
|
||||||
|
export { FormularioForm }
|
||||||
|
|
||||||
|
declare const FormularioField: DefineComponent<{
|
||||||
|
name: string;
|
||||||
|
value?: unknown;
|
||||||
|
validation?: string|any[];
|
||||||
|
/** Defaults to 'demand' */
|
||||||
|
validationBehavior?: ValidationBehaviour;
|
||||||
|
validationRules?: Record<string, ValidationRuleFn>;
|
||||||
|
validationMessages?: Record<string, ValidationMessageI18NFn|string>;
|
||||||
|
errorsDisabled?: boolean;
|
||||||
|
modelGetConverter?: ModelGetConverter;
|
||||||
|
modelSetConverter?: ModelSetConverter;
|
||||||
|
/** Defaults to 'none' */
|
||||||
|
unregisterBehavior?: UnregisterBehaviour;
|
||||||
|
tag?: string;
|
||||||
|
}, {
|
||||||
|
runValidation(): Promise<Violation[]>;
|
||||||
|
hasValidationErrors (): Promise<boolean>;
|
||||||
|
/** @internal */
|
||||||
|
resetValidation(): void;
|
||||||
|
}>
|
||||||
|
|
||||||
|
export { FormularioField }
|
||||||
|
|
||||||
|
declare class Formulario {
|
||||||
|
public validationRules: Record<string, ValidationRuleFn>;
|
||||||
|
public validationMessages: Record<string, ValidationMessageI18NFn|string>;
|
||||||
|
|
||||||
|
constructor (options?: Options);
|
||||||
|
|
||||||
|
/** Given a set of options, apply them to the pre-existing options. */
|
||||||
|
public extend (extendWith: Options): Formulario;
|
||||||
|
|
||||||
|
public runValidation (id: string): Promise<Record<string, Violation[]>>;
|
||||||
|
|
||||||
|
public resetValidation (id: string): void;
|
||||||
|
|
||||||
|
/** Used by forms instances to add themselves into a registry */
|
||||||
|
public register (id: string, form: InstanceType<FormularioFormConstructor>): void;
|
||||||
|
|
||||||
|
/** Used by forms instances to remove themselves from a registry */
|
||||||
|
public unregister (id: string): void;
|
||||||
|
|
||||||
|
/** Get validation rules by merging any passed in with global rules. */
|
||||||
|
public getRules (extendWith: Record<string, ValidationRuleFn> = {}): Record<string, ValidationRuleFn>;
|
||||||
|
|
||||||
|
/** Get validation messages by merging any passed in with global messages. */
|
||||||
|
public getMessages (
|
||||||
|
vm: Vue,
|
||||||
|
extendWith: Record<string, ValidationMessageI18NFn|string>
|
||||||
|
): Record<string, ValidationMessageFn>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Formulario }
|
||||||
|
|
||||||
|
declare module 'vue/types/vue' {
|
||||||
|
interface Vue {
|
||||||
|
readonly $formulario: Formulario;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const VueFormulario: PluginObject<Options> & {
|
||||||
|
Formulario: Formulario,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VueFormulario
|
42
package.json
42
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@retailcrm/vue-formulario",
|
"name": "@retailcrm/vue-formulario",
|
||||||
"version": "0.7.1",
|
"version": "0.8.3",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": "RetailDriverLLC <integration@retailcrm.ru>",
|
"author": "RetailDriverLLC <integration@retailcrm.ru>",
|
||||||
"main": "dist/formulario.umd.js",
|
"main": "dist/formulario.umd.js",
|
||||||
|
@ -9,12 +9,22 @@
|
||||||
"./sfc": "src/index.ts"
|
"./sfc": "src/index.ts"
|
||||||
},
|
},
|
||||||
"unpkg": "dist/formulario.min.js",
|
"unpkg": "dist/formulario.min.js",
|
||||||
|
"web-types": "web-types.json",
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"types",
|
||||||
|
"CHANGELOG.md",
|
||||||
|
"LICENSE.txt",
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-plain-object": "^3.0.0",
|
|
||||||
"is-url": "^1.2.4",
|
"is-url": "^1.2.4",
|
||||||
"vue-class-component": "^7.2.3",
|
"vue-class-component": "^7.2.3",
|
||||||
"vue-property-decorator": "^8.4.2"
|
"vue-property-decorator": "^8.4.2"
|
||||||
},
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "^2.6"
|
||||||
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/retailcrm/vue-formulario/issues"
|
"url": "https://github.com/retailcrm/vue-formulario/issues"
|
||||||
},
|
},
|
||||||
|
@ -24,7 +34,7 @@
|
||||||
"build:iife": "rollup --config build/rollup.iife.config.js --format iife --file dist/formulario.min.js",
|
"build:iife": "rollup --config build/rollup.iife.config.js --format iife --file dist/formulario.min.js",
|
||||||
"build:size": "gzip -c dist/formulario.esm.js | wc -c",
|
"build:size": "gzip -c dist/formulario.esm.js | wc -c",
|
||||||
"build:umd": "rollup --config build/rollup.config.js --format umd --file dist/formulario.umd.js",
|
"build:umd": "rollup --config build/rollup.config.js --format umd --file dist/formulario.umd.js",
|
||||||
"lint": "vue-cli-service lint",
|
"lint": "eslint --ext .js,.mjs,.ts,.vue",
|
||||||
"release": "standard-version",
|
"release": "standard-version",
|
||||||
"release:minor": "standard-version --release-as minor",
|
"release:minor": "standard-version --release-as minor",
|
||||||
"release:patch": "standard-version --release-as patch",
|
"release:patch": "standard-version --release-as patch",
|
||||||
|
@ -52,32 +62,28 @@
|
||||||
"@storybook/vue": "^6.0.26",
|
"@storybook/vue": "^6.0.26",
|
||||||
"@types/is-url": "^1.2.28",
|
"@types/is-url": "^1.2.28",
|
||||||
"@types/jest": "^26.0.14",
|
"@types/jest": "^26.0.14",
|
||||||
"@typescript-eslint/eslint-plugin": "^2.26.0",
|
"@typescript-eslint/eslint-plugin": "^6.16.0",
|
||||||
"@typescript-eslint/parser": "^2.26.0",
|
"@typescript-eslint/parser": "^6.16.0",
|
||||||
"@vue/cli-plugin-babel": "^4.3.1",
|
"@vue/cli-plugin-babel": "^4.3.1",
|
||||||
"@vue/cli-plugin-eslint": "^4.3.1",
|
|
||||||
"@vue/cli-plugin-typescript": "^4.5.7",
|
"@vue/cli-plugin-typescript": "^4.5.7",
|
||||||
"@vue/cli-service": "^4.5.4",
|
"@vue/cli-service": "^4.5.4",
|
||||||
"@vue/component-compiler-utils": "^3.1.2",
|
"@vue/component-compiler-utils": "^3.1.2",
|
||||||
"@vue/eslint-config-standard": "^5.1.2",
|
|
||||||
"@vue/eslint-config-typescript": "^5.0.2",
|
|
||||||
"@vue/test-utils": "^1.0.2",
|
"@vue/test-utils": "^1.0.2",
|
||||||
"autoprefixer": "^9.7.6",
|
"autoprefixer": "^9.7.6",
|
||||||
"babel-core": "^7.0.0-bridge.0",
|
"babel-core": "^7.0.0-bridge.0",
|
||||||
"babel-eslint": "^10.1.0",
|
|
||||||
"babel-jest": "^25.5.1",
|
"babel-jest": "^25.5.1",
|
||||||
"bootstrap-scss": "^4.5.2",
|
"bootstrap-scss": "^4.5.2",
|
||||||
"eslint": "^5.16.0",
|
"eslint": "^8.56.0",
|
||||||
"eslint-config-standard": "^12.0.0",
|
"eslint-config-standard": "^17.1.0",
|
||||||
"eslint-plugin-import": "^2.20.1",
|
"eslint-friendly-formatter": "^4.0.1",
|
||||||
"eslint-plugin-node": "^8.0.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
"eslint-plugin-promise": "^4.1.1",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
"eslint-plugin-standard": "^4.0.0",
|
"eslint-plugin-promise": "^6.1.1",
|
||||||
"eslint-plugin-vue": "^5.2.3",
|
"eslint-plugin-vue": "^9.19.2",
|
||||||
"flush-promises": "^1.0.2",
|
"flush-promises": "^1.0.2",
|
||||||
"jest": "^26.5.2",
|
"jest": "^26.5.2",
|
||||||
"jest-vue-preprocessor": "^1.7.1",
|
"jest-vue-preprocessor": "^1.7.1",
|
||||||
"node-sass": "^4.14.1",
|
"node-sass": "^9.0.0",
|
||||||
"rollup": "^1.32.1",
|
"rollup": "^1.32.1",
|
||||||
"rollup-plugin-auto-external": "^2.0.0",
|
"rollup-plugin-auto-external": "^2.0.0",
|
||||||
"rollup-plugin-internal": "^1.0.4",
|
"rollup-plugin-internal": "^1.0.4",
|
||||||
|
@ -88,7 +94,7 @@
|
||||||
"sass-loader": "^10.0.3",
|
"sass-loader": "^10.0.3",
|
||||||
"standard-version": "^9.3.0",
|
"standard-version": "^9.3.0",
|
||||||
"ts-jest": "^26.4.1",
|
"ts-jest": "^26.4.1",
|
||||||
"typescript": "~3.9.3",
|
"typescript": "^4.9.5",
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
"vue-cli-plugin-storybook": "^1.3.0",
|
"vue-cli-plugin-storybook": "^1.3.0",
|
||||||
"vue-jest": "^3.0.5",
|
"vue-jest": "^3.0.5",
|
||||||
|
|
|
@ -1,33 +1,26 @@
|
||||||
import merge from '@/utils/merge'
|
import type { FormularioFormConstructor } from '../types/form'
|
||||||
import validationRules from '@/validation/rules'
|
|
||||||
import validationMessages from '@/validation/messages'
|
|
||||||
|
|
||||||
import {
|
import type {
|
||||||
ValidationContext,
|
ValidationContext,
|
||||||
ValidationRuleFn,
|
ValidationRuleFn,
|
||||||
ValidationMessageFn,
|
ValidationMessageFn,
|
||||||
ValidationMessageI18NFn,
|
ValidationMessageI18NFn,
|
||||||
Violation,
|
Violation,
|
||||||
} from '@/validation/validator'
|
} from '../types/validation'
|
||||||
|
|
||||||
import { FormularioForm } from '@/types'
|
import type { Options } from '../types/plugin'
|
||||||
|
|
||||||
export interface FormularioOptions {
|
import validationRules from '@/validation/rules'
|
||||||
validationRules?: Record<string, ValidationRuleFn>;
|
import validationMessages from '@/validation/messages'
|
||||||
validationMessages?: Record<string, ValidationMessageI18NFn|string>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The base formulario library.
|
|
||||||
*/
|
|
||||||
export default class Formulario {
|
export default class Formulario {
|
||||||
public validationRules: Record<string, ValidationRuleFn> = {}
|
public validationRules: Record<string, ValidationRuleFn> = {}
|
||||||
public validationMessages: Record<string, ValidationMessageI18NFn|string> = {}
|
public validationMessages: Record<string, ValidationMessageI18NFn|string> = {}
|
||||||
|
|
||||||
private readonly registry: Map<string, FormularioForm>
|
private readonly _registry: Map<string, InstanceType<FormularioFormConstructor>>
|
||||||
|
|
||||||
public constructor (options?: FormularioOptions) {
|
public constructor (options?: Options) {
|
||||||
this.registry = new Map()
|
this._registry = new Map()
|
||||||
|
|
||||||
this.validationRules = validationRules
|
this.validationRules = validationRules
|
||||||
this.validationMessages = validationMessages
|
this.validationMessages = validationMessages
|
||||||
|
@ -38,31 +31,31 @@ export default class Formulario {
|
||||||
/**
|
/**
|
||||||
* Given a set of options, apply them to the pre-existing options.
|
* Given a set of options, apply them to the pre-existing options.
|
||||||
*/
|
*/
|
||||||
public extend (extendWith: FormularioOptions): Formulario {
|
public extend (extendWith: Options): Formulario {
|
||||||
if (typeof extendWith === 'object') {
|
if (typeof extendWith === 'object') {
|
||||||
this.validationRules = merge(this.validationRules, extendWith.validationRules || {})
|
this.validationRules = { ...this.validationRules, ...(extendWith.validationRules || {}) }
|
||||||
this.validationMessages = merge(this.validationMessages, extendWith.validationMessages || {})
|
this.validationMessages = { ...this.validationMessages, ...(extendWith.validationMessages || {}) }
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
throw new Error(`[Formulario]: Formulario.extend(): should be passed an object (was ${typeof extendWith})`)
|
throw new Error(`[Formulario]: Formulario.extend(): should be passed an object (was ${typeof extendWith})`)
|
||||||
}
|
}
|
||||||
|
|
||||||
public runValidation (id: string): Promise<Record<string, Violation[]>> {
|
public runValidation (id: string): Promise<Record<string, Violation[]>> {
|
||||||
if (!this.registry.has(id)) {
|
if (!this._registry.has(id)) {
|
||||||
throw new Error(`[Formulario]: Formulario.runValidation(): no forms with id "${id}"`)
|
throw new Error(`[Formulario]: Formulario.runValidation(): no forms with id "${id}"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const form = this.registry.get(id) as FormularioForm
|
const form = this._registry.get(id) as InstanceType<FormularioFormConstructor>
|
||||||
|
|
||||||
return form.runValidation()
|
return form.runValidation()
|
||||||
}
|
}
|
||||||
|
|
||||||
public resetValidation (id: string): void {
|
public resetValidation (id: string): void {
|
||||||
if (!this.registry.has(id)) {
|
if (!this._registry.has(id)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const form = this.registry.get(id) as FormularioForm
|
const form = this._registry.get(id) as InstanceType<FormularioFormConstructor>
|
||||||
|
|
||||||
form.resetValidation()
|
form.resetValidation()
|
||||||
}
|
}
|
||||||
|
@ -71,12 +64,12 @@ export default class Formulario {
|
||||||
* Used by forms instances to add themselves into a registry
|
* Used by forms instances to add themselves into a registry
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public register (id: string, form: FormularioForm): void {
|
public register (id: string, form: InstanceType<FormularioFormConstructor>): void {
|
||||||
if (this.registry.has(id)) {
|
if (this._registry.has(id)) {
|
||||||
throw new Error(`[Formulario]: Formulario.register(): id "${id}" is already in use`)
|
throw new Error(`[Formulario]: Formulario.register(): id "${id}" is already in use`)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.registry.set(id, form)
|
this._registry.set(id, form)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,8 +77,8 @@ export default class Formulario {
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public unregister (id: string): void {
|
public unregister (id: string): void {
|
||||||
if (this.registry.has(id)) {
|
if (this._registry.has(id)) {
|
||||||
this.registry.delete(id)
|
this._registry.delete(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +87,7 @@ export default class Formulario {
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public getRules (extendWith: Record<string, ValidationRuleFn> = {}): Record<string, ValidationRuleFn> {
|
public getRules (extendWith: Record<string, ValidationRuleFn> = {}): Record<string, ValidationRuleFn> {
|
||||||
return merge(this.validationRules, extendWith)
|
return { ...this.validationRules, ...extendWith }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -102,12 +95,14 @@ export default class Formulario {
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public getMessages (vm: Vue, extendWith: Record<string, ValidationMessageI18NFn|string>): Record<string, ValidationMessageFn> {
|
public getMessages (vm: Vue, extendWith: Record<string, ValidationMessageI18NFn|string>): Record<string, ValidationMessageFn> {
|
||||||
const raw = merge(this.validationMessages || {}, extendWith)
|
const raw = { ...this.validationMessages, ...extendWith }
|
||||||
const messages: Record<string, ValidationMessageFn> = {}
|
const messages: Record<string, ValidationMessageFn> = {}
|
||||||
|
|
||||||
for (const name in raw) {
|
for (const name in raw) {
|
||||||
messages[name] = (context: ValidationContext, ...args: any[]): string => {
|
messages[name] = (context: ValidationContext, ...args: unknown[]): string => {
|
||||||
return typeof raw[name] === 'string' ? raw[name] : raw[name](vm, context, ...args)
|
const fn = raw[name]
|
||||||
|
|
||||||
|
return typeof fn === 'string' ? fn : fn(vm, context, ...args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,21 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import type {
|
||||||
|
Context,
|
||||||
|
Empty,
|
||||||
|
ModelGetConverter,
|
||||||
|
ModelSetConverter,
|
||||||
|
ValidationBehaviour,
|
||||||
|
UnregisterBehaviour,
|
||||||
|
} from '../types/field'
|
||||||
|
|
||||||
|
import type {
|
||||||
|
ValidationRuleFn,
|
||||||
|
ValidationMessageI18NFn,
|
||||||
|
Violation,
|
||||||
|
} from '../types/validation'
|
||||||
|
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
|
@ -16,41 +31,22 @@ import {
|
||||||
Prop,
|
Prop,
|
||||||
Watch,
|
Watch,
|
||||||
} from 'vue-property-decorator'
|
} from 'vue-property-decorator'
|
||||||
|
|
||||||
|
import { processConstraints, validate } from '@/validation/validator'
|
||||||
|
|
||||||
import { deepEquals, has, snakeToCamel } from './utils'
|
import { deepEquals, has, snakeToCamel } from './utils'
|
||||||
import {
|
|
||||||
processConstraints,
|
|
||||||
validate,
|
|
||||||
ValidationRuleFn,
|
|
||||||
ValidationMessageI18NFn,
|
|
||||||
Violation,
|
|
||||||
} from '@/validation/validator'
|
|
||||||
|
|
||||||
import {
|
|
||||||
FormularioFieldContext,
|
|
||||||
FormularioFieldModelGetConverter as ModelGetConverter,
|
|
||||||
FormularioFieldModelSetConverter as ModelSetConverter,
|
|
||||||
Empty,
|
|
||||||
} from '@/types'
|
|
||||||
|
|
||||||
import { UNREGISTER_BEHAVIOR } from '@/enum'
|
|
||||||
|
|
||||||
const VALIDATION_BEHAVIOR = {
|
|
||||||
DEMAND: 'demand',
|
|
||||||
LIVE: 'live',
|
|
||||||
SUBMIT: 'submit',
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({ name: 'FormularioField', inheritAttrs: false })
|
@Component({ name: 'FormularioField', inheritAttrs: false })
|
||||||
export default class FormularioField extends Vue {
|
export default class FormularioField extends Vue {
|
||||||
@Inject({ default: '' }) __Formulario_path!: string
|
@Inject({ default: '' }) __Formulario_path!: string
|
||||||
@Inject({ default: undefined }) __FormularioForm_set!: Function|undefined
|
@Inject({ default: undefined }) __FormularioForm_set!: ((path: string, value: unknown) => void)|undefined
|
||||||
@Inject({ default: () => (): void => {} }) __FormularioForm_emitInput!: Function
|
@Inject({ default: () => (): void => {} }) __FormularioForm_emitInput!: () => void
|
||||||
@Inject({ default: () => (): void => {} }) __FormularioForm_emitValidation!: Function
|
@Inject({ default: () => (): void => {} }) __FormularioForm_emitValidation!: (path: string, violations: Violation[]) => void
|
||||||
@Inject({ default: undefined }) __FormularioForm_register!: Function|undefined
|
@Inject({ default: undefined }) __FormularioForm_register!: ((path: string, field: FormularioField) => void)|undefined
|
||||||
@Inject({ default: undefined }) __FormularioForm_unregister!: Function|undefined
|
@Inject({ default: undefined }) __FormularioForm_unregister!: ((path: string, behavior: UnregisterBehaviour) => void)|undefined
|
||||||
|
|
||||||
@Inject({ default: () => (): Record<string, unknown> => ({}) })
|
@Inject({ default: () => (): Record<string, unknown> => ({}) })
|
||||||
__FormularioForm_getState!: () => Record<string, unknown>
|
__FormularioForm_getState!: () => Record<string, unknown>
|
||||||
|
|
||||||
@Model('input', { default: '' }) value!: unknown
|
@Model('input', { default: '' }) value!: unknown
|
||||||
|
|
||||||
|
@ -63,9 +59,9 @@ export default class FormularioField extends Vue {
|
||||||
@Prop({ default: () => ({}) }) validationRules!: Record<string, ValidationRuleFn>
|
@Prop({ default: () => ({}) }) validationRules!: Record<string, ValidationRuleFn>
|
||||||
@Prop({ default: () => ({}) }) validationMessages!: Record<string, ValidationMessageI18NFn|string>
|
@Prop({ default: () => ({}) }) validationMessages!: Record<string, ValidationMessageI18NFn|string>
|
||||||
@Prop({
|
@Prop({
|
||||||
default: VALIDATION_BEHAVIOR.DEMAND,
|
default: 'demand',
|
||||||
validator: behavior => Object.values(VALIDATION_BEHAVIOR).includes(behavior)
|
validator: (behavior: string) => ['demand', 'live', 'submit'].includes(behavior)
|
||||||
}) validationBehavior!: string
|
}) validationBehavior!: ValidationBehaviour
|
||||||
|
|
||||||
// Affects only setting of local errors
|
// Affects only setting of local errors
|
||||||
@Prop({ default: false }) errorsDisabled!: boolean
|
@Prop({ default: false }) errorsDisabled!: boolean
|
||||||
|
@ -74,7 +70,7 @@ export default class FormularioField extends Vue {
|
||||||
@Prop({ default: () => <T, U>(value: U|T): U|T => value }) modelSetConverter!: ModelSetConverter
|
@Prop({ default: () => <T, U>(value: U|T): U|T => value }) modelSetConverter!: ModelSetConverter
|
||||||
|
|
||||||
@Prop({ default: 'div' }) tag!: string
|
@Prop({ default: 'div' }) tag!: string
|
||||||
@Prop({ default: UNREGISTER_BEHAVIOR.NONE }) unregisterBehavior!: string
|
@Prop({ default: 'none' }) unregisterBehavior!: UnregisterBehaviour
|
||||||
|
|
||||||
public proxy: unknown = this.hasModel ? this.value : ''
|
public proxy: unknown = this.hasModel ? this.value : ''
|
||||||
|
|
||||||
|
@ -88,14 +84,12 @@ export default class FormularioField extends Vue {
|
||||||
return this.__Formulario_path !== '' ? `${this.__Formulario_path}.${this.name}` : this.name
|
return this.__Formulario_path !== '' ? `${this.__Formulario_path}.${this.name}` : this.name
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Determines if this formulario element is v-modeled or not. */
|
||||||
* Determines if this formulario element is v-modeled or not.
|
|
||||||
*/
|
|
||||||
public get hasModel (): boolean {
|
public get hasModel (): boolean {
|
||||||
return has(this.$options.propsData || {}, 'value')
|
return has(this.$options.propsData || {}, 'value')
|
||||||
}
|
}
|
||||||
|
|
||||||
private get context (): FormularioFieldContext<unknown> {
|
private get context (): Context<unknown> {
|
||||||
return Object.defineProperty({
|
return Object.defineProperty({
|
||||||
name: this.fullPath,
|
name: this.fullPath,
|
||||||
path: this.fullPath,
|
path: this.fullPath,
|
||||||
|
@ -103,15 +97,15 @@ export default class FormularioField extends Vue {
|
||||||
violations: this.violations,
|
violations: this.violations,
|
||||||
errors: this.localErrors,
|
errors: this.localErrors,
|
||||||
allErrors: [...this.localErrors, ...this.violations.map(v => v.message)],
|
allErrors: [...this.localErrors, ...this.violations.map(v => v.message)],
|
||||||
}, 'model', {
|
} as Context<unknown>, 'model', {
|
||||||
get: () => this.modelGetConverter(this.proxy),
|
get: () => this.modelGetConverter(this.proxy),
|
||||||
set: (value: unknown): void => {
|
set: (value: unknown): void => {
|
||||||
this.syncProxy(this.modelSetConverter(value, this.proxy))
|
this._syncProxy(this.modelSetConverter(value, this.proxy))
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private get normalizedValidationRules (): Record<string, ValidationRuleFn> {
|
private get _normalizedValidationRules (): Record<string, ValidationRuleFn> {
|
||||||
const rules: Record<string, ValidationRuleFn> = {}
|
const rules: Record<string, ValidationRuleFn> = {}
|
||||||
Object.keys(this.validationRules).forEach(key => {
|
Object.keys(this.validationRules).forEach(key => {
|
||||||
rules[snakeToCamel(key)] = this.validationRules[key]
|
rules[snakeToCamel(key)] = this.validationRules[key]
|
||||||
|
@ -119,7 +113,7 @@ export default class FormularioField extends Vue {
|
||||||
return rules
|
return rules
|
||||||
}
|
}
|
||||||
|
|
||||||
private get normalizedValidationMessages (): Record<string, ValidationMessageI18NFn|string> {
|
private get _normalizedValidationMessages (): Record<string, ValidationMessageI18NFn|string> {
|
||||||
const messages: Record<string, ValidationMessageI18NFn|string> = {}
|
const messages: Record<string, ValidationMessageI18NFn|string> = {}
|
||||||
Object.keys(this.validationMessages).forEach(key => {
|
Object.keys(this.validationMessages).forEach(key => {
|
||||||
messages[snakeToCamel(key)] = this.validationMessages[key]
|
messages[snakeToCamel(key)] = this.validationMessages[key]
|
||||||
|
@ -128,42 +122,70 @@ export default class FormularioField extends Vue {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Watch('value')
|
@Watch('value')
|
||||||
private onValueChange (): void {
|
private _onValueChange (): void {
|
||||||
this.syncProxy(this.value)
|
this._syncProxy(this.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Watch('proxy')
|
@Watch('proxy')
|
||||||
private onProxyChange (): void {
|
private _onProxyChange (): void {
|
||||||
if (this.validationBehavior === VALIDATION_BEHAVIOR.LIVE) {
|
if (this.validationBehavior === 'live') {
|
||||||
this.runValidation()
|
this.runValidation()
|
||||||
} else {
|
} else {
|
||||||
this.resetValidation()
|
this.resetValidation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @internal */
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
public created (): void {
|
public created (): void {
|
||||||
if (typeof this.__FormularioForm_register === 'function') {
|
if (typeof this.__FormularioForm_register === 'function') {
|
||||||
this.__FormularioForm_register(this.fullPath, this)
|
this.__FormularioForm_register(this.fullPath, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.validationBehavior === VALIDATION_BEHAVIOR.LIVE) {
|
if (this.validationBehavior === 'live') {
|
||||||
this.runValidation()
|
this.runValidation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @internal */
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
public beforeDestroy (): void {
|
public beforeDestroy (): void {
|
||||||
if (typeof this.__FormularioForm_unregister === 'function') {
|
if (typeof this.__FormularioForm_unregister === 'function') {
|
||||||
this.__FormularioForm_unregister(this.fullPath, this.unregisterBehavior)
|
this.__FormularioForm_unregister(this.fullPath, this.unregisterBehavior)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private syncProxy (value: unknown): void {
|
public runValidation (): Promise<Violation[]> {
|
||||||
|
this.validationRun = this._validate().then(violations => {
|
||||||
|
this.violations = violations
|
||||||
|
this._emitValidation(this.fullPath, violations)
|
||||||
|
|
||||||
|
return this.violations
|
||||||
|
})
|
||||||
|
|
||||||
|
return this.validationRun
|
||||||
|
}
|
||||||
|
|
||||||
|
public hasValidationErrors (): Promise<boolean> {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.validationRun.then(() => resolve(this.violations.length > 0))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
public setErrors (errors: string[]): void {
|
||||||
|
if (!this.errorsDisabled) {
|
||||||
|
this.localErrors = errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
public resetValidation (): void {
|
||||||
|
this.localErrors = []
|
||||||
|
this.violations = []
|
||||||
|
}
|
||||||
|
|
||||||
|
private _syncProxy (value: unknown): void {
|
||||||
if (!deepEquals(value, this.proxy)) {
|
if (!deepEquals(value, this.proxy)) {
|
||||||
this.proxy = value
|
this.proxy = value
|
||||||
this.$emit('input', value)
|
this.$emit('input', value)
|
||||||
|
@ -175,22 +197,11 @@ export default class FormularioField extends Vue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public runValidation (): Promise<Violation[]> {
|
private _validate (): Promise<Violation[]> {
|
||||||
this.validationRun = this.validate().then(violations => {
|
|
||||||
this.violations = violations
|
|
||||||
this.emitValidation(this.fullPath, violations)
|
|
||||||
|
|
||||||
return this.violations
|
|
||||||
})
|
|
||||||
|
|
||||||
return this.validationRun
|
|
||||||
}
|
|
||||||
|
|
||||||
private validate (): Promise<Violation[]> {
|
|
||||||
return validate(processConstraints(
|
return validate(processConstraints(
|
||||||
this.validation,
|
this.validation,
|
||||||
this.$formulario.getRules(this.normalizedValidationRules),
|
this.$formulario.getRules(this._normalizedValidationRules),
|
||||||
this.$formulario.getMessages(this, this.normalizedValidationMessages),
|
this.$formulario.getMessages(this, this._normalizedValidationMessages),
|
||||||
), {
|
), {
|
||||||
value: this.proxy,
|
value: this.proxy,
|
||||||
name: this.fullPath,
|
name: this.fullPath,
|
||||||
|
@ -198,36 +209,11 @@ export default class FormularioField extends Vue {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private emitValidation (path: string, violations: Violation[]): void {
|
private _emitValidation (path: string, violations: Violation[]): void {
|
||||||
this.$emit('validation', { path, violations })
|
this.$emit('validation', { path, violations })
|
||||||
if (typeof this.__FormularioForm_emitValidation === 'function') {
|
if (typeof this.__FormularioForm_emitValidation === 'function') {
|
||||||
this.__FormularioForm_emitValidation(path, violations)
|
this.__FormularioForm_emitValidation(path, violations)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public hasValidationErrors (): Promise<boolean> {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.validationRun.then(() => resolve(this.violations.length > 0))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
public setErrors (errors: string[]): void {
|
|
||||||
if (!this.errorsDisabled) {
|
|
||||||
this.localErrors = errors
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
public resetValidation (): void {
|
|
||||||
this.localErrors = []
|
|
||||||
this.violations = []
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -5,7 +5,11 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import type { UnregisterBehaviour } from '../types/field'
|
||||||
|
import type { Violation } from '../types/validation'
|
||||||
|
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
Model,
|
Model,
|
||||||
|
@ -13,21 +17,18 @@ import {
|
||||||
Provide,
|
Provide,
|
||||||
Watch,
|
Watch,
|
||||||
} from 'vue-property-decorator'
|
} from 'vue-property-decorator'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
id,
|
id,
|
||||||
clone,
|
clone,
|
||||||
deepEquals,
|
deepEquals,
|
||||||
get,
|
get,
|
||||||
has,
|
has,
|
||||||
merge,
|
|
||||||
set,
|
set,
|
||||||
unset,
|
unset,
|
||||||
} from '@/utils'
|
} from '@/utils'
|
||||||
|
|
||||||
import { FormularioField } from '@/types'
|
import { FormularioField } from '@/types'
|
||||||
import { Violation } from '@/validation/validator'
|
|
||||||
|
|
||||||
import { UNREGISTER_BEHAVIOR } from '@/enum'
|
|
||||||
|
|
||||||
const update = (state: Record<string, unknown>, path: string, value: unknown): Record<string, unknown> => {
|
const update = (state: Record<string, unknown>, path: string, value: unknown): Record<string, unknown> => {
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
|
@ -57,7 +58,7 @@ export default class FormularioForm extends Vue {
|
||||||
private localFormErrors: string[] = []
|
private localFormErrors: string[] = []
|
||||||
|
|
||||||
private get fieldsErrorsComputed (): Record<string, string[]> {
|
private get fieldsErrorsComputed (): Record<string, string[]> {
|
||||||
return merge(this.fieldsErrors || {}, this.localFieldsErrors)
|
return { ...this.fieldsErrors, ...this.localFieldsErrors }
|
||||||
}
|
}
|
||||||
|
|
||||||
private get formErrorsComputed (): string[] {
|
private get formErrorsComputed (): string[] {
|
||||||
|
@ -90,11 +91,11 @@ export default class FormularioForm extends Vue {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provide('__FormularioForm_unregister')
|
@Provide('__FormularioForm_unregister')
|
||||||
private unregister (path: string, behavior: string): void {
|
private unregister (path: string, behavior: UnregisterBehaviour): void {
|
||||||
if (this.registry.has(path)) {
|
if (this.registry.has(path)) {
|
||||||
this.registry.delete(path)
|
this.registry.delete(path)
|
||||||
|
|
||||||
if (behavior === UNREGISTER_BEHAVIOR.UNSET) {
|
if (behavior === 'unset') {
|
||||||
this.proxy = unset(this.proxy, path) as Record<string, unknown>
|
this.proxy = unset(this.proxy, path) as Record<string, unknown>
|
||||||
this.emitInput()
|
this.emitInput()
|
||||||
}
|
}
|
||||||
|
@ -183,17 +184,17 @@ export default class FormularioForm extends Vue {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public setErrors ({ fieldsErrors, formErrors }: {
|
public setErrors ({ formErrors, fieldsErrors }: {
|
||||||
fieldsErrors?: Record<string, string[]>;
|
|
||||||
formErrors?: string[];
|
formErrors?: string[];
|
||||||
|
fieldsErrors?: Record<string, string[]>;
|
||||||
}): void {
|
}): void {
|
||||||
this.localFieldsErrors = fieldsErrors || {}
|
|
||||||
this.localFormErrors = formErrors || []
|
this.localFormErrors = formErrors || []
|
||||||
|
this.localFieldsErrors = fieldsErrors || {}
|
||||||
}
|
}
|
||||||
|
|
||||||
public resetValidation (): void {
|
public resetValidation (): void {
|
||||||
this.localFieldsErrors = {}
|
|
||||||
this.localFormErrors = []
|
this.localFormErrors = []
|
||||||
|
this.localFieldsErrors = {}
|
||||||
this.registry.forEach((field: FormularioField) => {
|
this.registry.forEach((field: FormularioField) => {
|
||||||
field.resetValidation()
|
field.resetValidation()
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
export const UNREGISTER_BEHAVIOR = {
|
|
||||||
NONE: 'none',
|
|
||||||
UNSET: 'unset',
|
|
||||||
}
|
|
19
src/index.ts
19
src/index.ts
|
@ -1,23 +1,26 @@
|
||||||
import { VueConstructor } from 'vue'
|
import type { VueConstructor } from 'vue'
|
||||||
|
import type { Options } from '../types/plugin'
|
||||||
|
|
||||||
import Formulario, { FormularioOptions } from '@/Formulario.ts'
|
import Formulario from '@/Formulario'
|
||||||
|
|
||||||
import FormularioField from '@/FormularioField.vue'
|
import FormularioField from '@/FormularioField.vue'
|
||||||
import FormularioFieldGroup from '@/FormularioFieldGroup.vue'
|
import FormularioFieldGroup from '@/FormularioFieldGroup.vue'
|
||||||
import FormularioForm from '@/FormularioForm.vue'
|
import FormularioForm from '@/FormularioForm.vue'
|
||||||
|
|
||||||
|
export {
|
||||||
|
Formulario,
|
||||||
|
FormularioField,
|
||||||
|
FormularioFieldGroup,
|
||||||
|
FormularioForm,
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Formulario,
|
Formulario,
|
||||||
install (Vue: VueConstructor, options?: FormularioOptions): void {
|
install (Vue: VueConstructor, options?: Options): void {
|
||||||
Vue.component('FormularioField', FormularioField)
|
Vue.component('FormularioField', FormularioField)
|
||||||
Vue.component('FormularioFieldGroup', FormularioFieldGroup)
|
Vue.component('FormularioFieldGroup', FormularioFieldGroup)
|
||||||
Vue.component('FormularioForm', FormularioForm)
|
Vue.component('FormularioForm', FormularioForm)
|
||||||
|
|
||||||
// @deprecated Use FormularioField instead
|
|
||||||
Vue.component('FormularioInput', FormularioField)
|
|
||||||
// @deprecated Use FormularioFieldGroup instead
|
|
||||||
Vue.component('FormularioGrouping', FormularioFieldGroup)
|
|
||||||
|
|
||||||
Vue.mixin({
|
Vue.mixin({
|
||||||
beforeCreate () {
|
beforeCreate () {
|
||||||
const o = this.$options as Record<string, any>
|
const o = this.$options as Record<string, any>
|
||||||
|
|
9
src/shims-ext.d.ts
vendored
9
src/shims-ext.d.ts
vendored
|
@ -3,12 +3,7 @@ import Formulario from '@/Formulario'
|
||||||
declare module 'vue/types/vue' {
|
declare module 'vue/types/vue' {
|
||||||
interface Vue {
|
interface Vue {
|
||||||
$formulario: Formulario;
|
$formulario: Formulario;
|
||||||
$route: VueRoute;
|
$t: any;
|
||||||
$t: Function;
|
$tc: any;
|
||||||
$tc: Function;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface VueRoute {
|
|
||||||
path: string;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
29
src/types.ts
29
src/types.ts
|
@ -1,10 +1,6 @@
|
||||||
import Vue from 'vue'
|
import type { Violation } from '../types/validation'
|
||||||
import { Violation } from '@/validation/validator'
|
|
||||||
|
|
||||||
export interface FormularioForm extends Vue {
|
import Vue from 'vue'
|
||||||
runValidation(): Promise<Record<string, Violation[]>>;
|
|
||||||
resetValidation(): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FormularioField extends Vue {
|
export interface FormularioField extends Vue {
|
||||||
hasModel: boolean;
|
hasModel: boolean;
|
||||||
|
@ -14,25 +10,6 @@ export interface FormularioField extends Vue {
|
||||||
resetValidation(): void;
|
resetValidation(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FormularioFieldContext<T> = {
|
|
||||||
model: T;
|
|
||||||
name: string;
|
|
||||||
runValidation(): Promise<Violation[]>;
|
|
||||||
violations: Violation[];
|
|
||||||
errors: string[];
|
|
||||||
allErrors: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FormularioFieldModelGetConverter {
|
|
||||||
<U, T>(value: U|Empty): U|T|Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FormularioFieldModelSetConverter {
|
|
||||||
<T, U>(curr: U|T, prev: U|Empty): U|T;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Empty = undefined | null
|
|
||||||
|
|
||||||
export enum TYPE {
|
export enum TYPE {
|
||||||
ARRAY = 'ARRAY',
|
ARRAY = 'ARRAY',
|
||||||
BIGINT = 'BIGINT',
|
BIGINT = 'BIGINT',
|
||||||
|
@ -95,7 +72,7 @@ export function typeOf (value: unknown): string {
|
||||||
return 'InstanceOf<' + (constructorOf(value) as { name?: string }).name + '>'
|
return 'InstanceOf<' + (constructorOf(value) as { name?: string }).name + '>'
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error()
|
throw new Error('[Formulario] typeOf - unknown type detected')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isScalar (value: unknown): boolean {
|
export function isScalar (value: unknown): boolean {
|
||||||
|
|
|
@ -9,7 +9,8 @@ const cloneInstance = <T>(original: T): T => {
|
||||||
* case of needing to unbind reactive watchers.
|
* case of needing to unbind reactive watchers.
|
||||||
*/
|
*/
|
||||||
export default function clone<T = unknown> (value: T): T {
|
export default function clone<T = unknown> (value: T): T {
|
||||||
if (isScalar(value)) {
|
// scalars & immutables
|
||||||
|
if (isScalar(value) || value instanceof Blob) {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
export { default as id } from './id'
|
export { default as id } from './id'
|
||||||
export { default as clone } from './clone'
|
export { default as clone } from './clone'
|
||||||
export { default as has } from './has'
|
export { default as has } from './has'
|
||||||
export { default as merge } from './merge'
|
|
||||||
export { get, set, unset } from './access'
|
export { get, set, unset } from './access'
|
||||||
export { default as regexForFormat } from './regexForFormat'
|
export { default as regexForFormat } from './regexForFormat'
|
||||||
export { deepEquals, shallowEquals } from './compare'
|
export { deepEquals, shallowEquals } from './compare'
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
import isPlainObject from 'is-plain-object'
|
|
||||||
import has from '@/utils/has.ts'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new object by copying properties of base and mergeWith.
|
|
||||||
* Note: arrays don't overwrite - they push
|
|
||||||
*
|
|
||||||
* @param {Object} a
|
|
||||||
* @param {Object} b
|
|
||||||
* @param {boolean} concatArrays
|
|
||||||
*/
|
|
||||||
export default function merge (
|
|
||||||
a: Record<string, any>,
|
|
||||||
b: Record<string, any>,
|
|
||||||
concatArrays = true
|
|
||||||
): Record<string, any> {
|
|
||||||
const merged: Record<string, any> = {}
|
|
||||||
|
|
||||||
for (const key in a) {
|
|
||||||
if (has(b, key)) {
|
|
||||||
if (isPlainObject(b[key]) && isPlainObject(a[key])) {
|
|
||||||
merged[key] = merge(a[key], b[key], concatArrays)
|
|
||||||
} else if (concatArrays && Array.isArray(a[key]) && Array.isArray(b[key])) {
|
|
||||||
merged[key] = a[key].concat(b[key])
|
|
||||||
} else {
|
|
||||||
merged[key] = b[key]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
merged[key] = a[key]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const prop in b) {
|
|
||||||
if (!has(merged, prop)) {
|
|
||||||
merged[prop] = b[prop]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return merged
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {
|
import type {
|
||||||
ValidationContext,
|
ValidationContext,
|
||||||
ValidationMessageI18NFn,
|
ValidationMessageI18NFn,
|
||||||
} from '@/validation/validator'
|
} from '../../types/validation'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message builders, names match rules names, see @/validation/rules
|
* Message builders, names match rules names, see @/validation/rules
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import isUrl from 'is-url'
|
import type {
|
||||||
import { has, regexForFormat, shallowEquals } from '@/utils'
|
|
||||||
import {
|
|
||||||
ValidationContext,
|
ValidationContext,
|
||||||
ValidationRuleFn,
|
ValidationRuleFn,
|
||||||
} from '@/validation/validator'
|
} from '../../types/validation'
|
||||||
|
|
||||||
|
import isUrl from 'is-url'
|
||||||
|
import { has, regexForFormat, shallowEquals } from '@/utils'
|
||||||
|
|
||||||
const rules: Record<string, ValidationRuleFn> = {
|
const rules: Record<string, ValidationRuleFn> = {
|
||||||
/**
|
/**
|
||||||
|
@ -165,7 +166,7 @@ const rules: Record<string, ValidationRuleFn> = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof value === 'string' || (force === 'length')) {
|
if (typeof value === 'string' || (force === 'length')) {
|
||||||
value = !isNaN(value) ? value.toString() : value
|
value = !isNaN(value) ? String(value) : value
|
||||||
return value.length <= maximum
|
return value.length <= maximum
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +188,7 @@ const rules: Record<string, ValidationRuleFn> = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof value === 'string' || (force === 'length')) {
|
if (typeof value === 'string' || (force === 'length')) {
|
||||||
value = !isNaN(value) ? value.toString() : value
|
value = !isNaN(value) ? String(value) : value
|
||||||
return value.length >= minimum
|
return value.length >= minimum
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,42 +1,14 @@
|
||||||
|
import type {
|
||||||
|
ValidationContext,
|
||||||
|
ValidationMessageFn,
|
||||||
|
ValidationRuleFn,
|
||||||
|
Validator,
|
||||||
|
ValidatorGroup,
|
||||||
|
Violation,
|
||||||
|
} from '../../types/validation'
|
||||||
|
|
||||||
import { has, snakeToCamel } from '@/utils'
|
import { has, snakeToCamel } from '@/utils'
|
||||||
|
|
||||||
export interface Validator {
|
|
||||||
(context: ValidationContext): Promise<Violation|null>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Violation {
|
|
||||||
message: string;
|
|
||||||
rule: string|null;
|
|
||||||
args: any[];
|
|
||||||
context: ValidationContext|null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ValidationRuleFn {
|
|
||||||
(context: ValidationContext, ...args: any[]): Promise<boolean>|boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ValidationMessageFn {
|
|
||||||
(context: ValidationContext, ...args: any[]): string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ValidationMessageI18NFn {
|
|
||||||
(vm: Vue, context: ValidationContext, ...args: any[]): string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ValidationContext {
|
|
||||||
// The value of the field (do not mutate!),
|
|
||||||
value: any;
|
|
||||||
// If wrapped in a FormulateForm, the value of other form fields.
|
|
||||||
formValues: Record<string, any>;
|
|
||||||
// The validation name to be used
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ValidatorGroup = {
|
|
||||||
validators: Validator[];
|
|
||||||
bail: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createValidator (
|
export function createValidator (
|
||||||
ruleFn: ValidationRuleFn,
|
ruleFn: ValidationRuleFn,
|
||||||
ruleName: string|null,
|
ruleName: string|null,
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { mount } from '@vue/test-utils'
|
||||||
import flushPromises from 'flush-promises'
|
import flushPromises from 'flush-promises'
|
||||||
|
|
||||||
import Formulario from '@/index.ts'
|
import Formulario from '@/index.ts'
|
||||||
import FormularioFieldGroup from '@/FormularioFieldGroup.vue'
|
|
||||||
import FormularioForm from '@/FormularioForm.vue'
|
import FormularioForm from '@/FormularioForm.vue'
|
||||||
|
|
||||||
Vue.use(Formulario)
|
Vue.use(Formulario)
|
||||||
|
|
|
@ -76,4 +76,11 @@ describe('clone', () => {
|
||||||
expect(copy.sample.doSomething).toBeTruthy()
|
expect(copy.sample.doSomething).toBeTruthy()
|
||||||
expect(copy.sample.doSomething).not.toThrow()
|
expect(copy.sample.doSomething).not.toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('does not create a copy of a blob', () => {
|
||||||
|
const blob = new Blob(['{"fieldA": "fieldA"}'], { type : 'application/json' })
|
||||||
|
const copy = clone(blob)
|
||||||
|
|
||||||
|
expect(blob === copy).toBeTruthy()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
import merge from '@/utils/merge.ts'
|
|
||||||
|
|
||||||
describe('merge', () => {
|
|
||||||
it('Can merge simple object', () => {
|
|
||||||
expect(merge({
|
|
||||||
optionA: true,
|
|
||||||
optionB: '1234',
|
|
||||||
}, {
|
|
||||||
optionA: false,
|
|
||||||
})).toEqual({
|
|
||||||
optionA: false,
|
|
||||||
optionB: '1234',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Can add to simple array', () => {
|
|
||||||
expect(merge({
|
|
||||||
optionA: true,
|
|
||||||
optionB: ['first', 'second']
|
|
||||||
}, {
|
|
||||||
optionB: ['third']
|
|
||||||
}, true)).toEqual({
|
|
||||||
optionA: true,
|
|
||||||
optionB: ['first', 'second', 'third']
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Can merge recursively', () => {
|
|
||||||
expect(merge({
|
|
||||||
optionA: true,
|
|
||||||
optionC: {
|
|
||||||
first: '123',
|
|
||||||
third: {
|
|
||||||
a: 'b',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
optionB: '1234',
|
|
||||||
}, {
|
|
||||||
optionB: '567',
|
|
||||||
optionC: {
|
|
||||||
first: '1234',
|
|
||||||
second: '789',
|
|
||||||
}
|
|
||||||
})).toEqual({
|
|
||||||
optionA: true,
|
|
||||||
optionC: {
|
|
||||||
first: '1234',
|
|
||||||
third: {
|
|
||||||
a: 'b',
|
|
||||||
},
|
|
||||||
second: '789',
|
|
||||||
},
|
|
||||||
optionB: '567',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
34
types/field.d.ts
vendored
Normal file
34
types/field.d.ts
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import type { Violation } from './validation'
|
||||||
|
|
||||||
|
export type Empty = undefined | null
|
||||||
|
|
||||||
|
export type Context<T> = {
|
||||||
|
model: T;
|
||||||
|
name: string;
|
||||||
|
path: string;
|
||||||
|
violations: Violation[];
|
||||||
|
errors: string[];
|
||||||
|
allErrors: string[];
|
||||||
|
runValidation(): Promise<Violation[]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ModelGetConverter {
|
||||||
|
<U, T>(value: U|Empty): U|T|Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ModelSetConverter {
|
||||||
|
<T, U>(curr: U|T, prev: U|Empty): U|T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* - 'demand': triggers validation on manual call
|
||||||
|
* - 'live': triggers validation on any changes
|
||||||
|
* - 'submit': triggers validation on form submit event
|
||||||
|
*/
|
||||||
|
export type ValidationBehaviour = 'demand' | 'live' | 'submit'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* - 'none': no any specific effects
|
||||||
|
* - 'unset': the value under field's path will be unset and path will be removed from the state
|
||||||
|
*/
|
||||||
|
export type UnregisterBehaviour = 'none' | 'unset'
|
17
types/form.d.ts
vendored
Normal file
17
types/form.d.ts
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import type { DefineComponent } from './vue'
|
||||||
|
import type { Violation } from './validation'
|
||||||
|
|
||||||
|
export type FormularioFormConstructor = DefineComponent<{
|
||||||
|
id?: string;
|
||||||
|
state?: Record<string, unknown>;
|
||||||
|
fieldsErrors?: Record<string, string[]>;
|
||||||
|
formErrors?: string[];
|
||||||
|
}, {
|
||||||
|
setErrors ({ formErrors, fieldsErrors }: {
|
||||||
|
formErrors?: string[];
|
||||||
|
fieldsErrors?: Record<string, string[]>;
|
||||||
|
}): void;
|
||||||
|
runValidation(): Promise<Record<string, Violation[]>>;
|
||||||
|
hasValidationErrors (): Promise<boolean>;
|
||||||
|
resetValidation(): void;
|
||||||
|
}>
|
9
types/plugin.d.ts
vendored
Normal file
9
types/plugin.d.ts
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import type {
|
||||||
|
ValidationMessageI18NFn,
|
||||||
|
ValidationRuleFn
|
||||||
|
} from './validation'
|
||||||
|
|
||||||
|
export interface Options {
|
||||||
|
validationRules?: Record<string, ValidationRuleFn>;
|
||||||
|
validationMessages?: Record<string, ValidationMessageI18NFn|string>;
|
||||||
|
}
|
38
types/validation.d.ts
vendored
Normal file
38
types/validation.d.ts
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import { Vue } from 'vue/types/vue'
|
||||||
|
|
||||||
|
export interface ValidationContext {
|
||||||
|
// The value of the field (do not mutate!),
|
||||||
|
value: any;
|
||||||
|
// If wrapped in a FormulateForm, the value of other form fields.
|
||||||
|
formValues: Record<string, any>;
|
||||||
|
// The validation name to be used
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Violation {
|
||||||
|
message: string;
|
||||||
|
rule: string|null;
|
||||||
|
args: any[];
|
||||||
|
context: ValidationContext|null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Validator {
|
||||||
|
(context: ValidationContext): Promise<Violation|null>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ValidatorGroup = {
|
||||||
|
validators: Validator[];
|
||||||
|
bail: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ValidationRuleFn {
|
||||||
|
(context: ValidationContext, ...args: any[]): Promise<boolean>|boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ValidationMessageFn {
|
||||||
|
(context: ValidationContext, ...args: any[]): string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ValidationMessageI18NFn {
|
||||||
|
(vm: Vue, context: ValidationContext, ...args: any[]): string;
|
||||||
|
}
|
3
types/vue.d.ts
vendored
Normal file
3
types/vue.d.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import type { Vue, VueConstructor } from 'vue/types/vue'
|
||||||
|
|
||||||
|
export type DefineComponent<Props, Methods> = VueConstructor<Vue & Required<Props> & Methods>
|
207
web-types.json
Normal file
207
web-types.json
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
|
||||||
|
"framework": "vue",
|
||||||
|
"name": "@omnica/accordion-vue2",
|
||||||
|
"version": "0.24.22",
|
||||||
|
"js-types-syntax": "typescript",
|
||||||
|
"description-markup": "markdown",
|
||||||
|
"contributions": {
|
||||||
|
"html": {
|
||||||
|
"vue-components": [
|
||||||
|
{
|
||||||
|
"name": "FormularioForm",
|
||||||
|
"description": "Form root",
|
||||||
|
"source": {
|
||||||
|
"module": "@retailcrm/vue-formulario",
|
||||||
|
"symbol": "FormularioForm"
|
||||||
|
},
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"name": "state",
|
||||||
|
"type": "object",
|
||||||
|
"default": "{}",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"type": "string",
|
||||||
|
"default": "id('formulario-form')",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fieldsErrors",
|
||||||
|
"type": "object",
|
||||||
|
"default": "{}",
|
||||||
|
"description": "Describes validation errors of concrete fields"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "formErrors",
|
||||||
|
"type": "array",
|
||||||
|
"default": "[]",
|
||||||
|
"description": "Describes validation errors of entire state"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"name": "input",
|
||||||
|
"description": "Occurs on state change",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"name": "...",
|
||||||
|
"type": {
|
||||||
|
"name": "any"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "validation",
|
||||||
|
"description": "Occurs at the end of a validation run",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"name": "...",
|
||||||
|
"type": {
|
||||||
|
"name": "any"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"slots": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"description": "Form content",
|
||||||
|
"scoped": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "FormularioField",
|
||||||
|
"description": "Form field",
|
||||||
|
"source": {
|
||||||
|
"module": "@retailcrm/vue-formulario",
|
||||||
|
"symbol": "FormularioField"
|
||||||
|
},
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"name": "value",
|
||||||
|
"type": "any",
|
||||||
|
"description": "The field's value, if not set explicitly, will be extracted from the state using 'path'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path to field's value in the state",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "validation",
|
||||||
|
"type": "string|array",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "validationRules",
|
||||||
|
"type": "object",
|
||||||
|
"description": "Validation rules override/extension opportunity",
|
||||||
|
"default": "{}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "validationMessages",
|
||||||
|
"type": "object",
|
||||||
|
"description": "Validation messages override/extension opportunity",
|
||||||
|
"default": "{}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "validationBehavior",
|
||||||
|
"type": "string",
|
||||||
|
"description": "",
|
||||||
|
"default": "'demand'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "errorsDisabled",
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Disables passing errors to the field from FormularioForm's fieldsErrors",
|
||||||
|
"default": "false"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "modelGetConverter",
|
||||||
|
"type": "function",
|
||||||
|
"description": "Simple middleware that provides opportunity to transform value before passing it to a template"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "modelSetConverter",
|
||||||
|
"type": "function",
|
||||||
|
"description": "Simple middleware that provides opportunity to transform new value before assigning"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tag",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Root element's tagName in lowercase"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "unregisterBehavior",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Possible values: 'none', 'unset'",
|
||||||
|
"default": "'none'"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"name": "input",
|
||||||
|
"description": "Occurs on value change",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"name": "...",
|
||||||
|
"type": {
|
||||||
|
"name": "any"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "validation",
|
||||||
|
"description": "Occurs at the end of a validation run",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"name": "...",
|
||||||
|
"type": {
|
||||||
|
"name": "any"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"slots": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"description": "Field content",
|
||||||
|
"scoped": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "FormularioFieldGroup",
|
||||||
|
"description": "Field group",
|
||||||
|
"source": {
|
||||||
|
"module": "@retailcrm/vue-formulario",
|
||||||
|
"symbol": "FormularioFieldGroup"
|
||||||
|
},
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path to a nested state",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"slots": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"description": "Group content"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue