|
- // Mixins
- import Colorable from '../colorable';
- import Themeable from '../themeable';
- import { inject as RegistrableInject } from '../registrable'; // Utilities
-
- import { deepEqual } from '../../util/helpers';
- import { consoleError } from '../../util/console';
- import mixins from '../../util/mixins';
- /* @vue/component */
-
- export default mixins(Colorable, RegistrableInject('form'), Themeable).extend({
- name: 'validatable',
- props: {
- disabled: Boolean,
- error: Boolean,
- errorCount: {
- type: [Number, String],
- default: 1
- },
- errorMessages: {
- type: [String, Array],
- default: () => []
- },
- messages: {
- type: [String, Array],
- default: () => []
- },
- readonly: Boolean,
- rules: {
- type: Array,
- default: () => []
- },
- success: Boolean,
- successMessages: {
- type: [String, Array],
- default: () => []
- },
- validateOnBlur: Boolean,
- value: {
- required: false
- }
- },
-
- data() {
- return {
- errorBucket: [],
- hasColor: false,
- hasFocused: false,
- hasInput: false,
- isFocused: false,
- isResetting: false,
- lazyValue: this.value,
- valid: false
- };
- },
-
- computed: {
- computedColor() {
- if (this.disabled) return undefined;
- if (this.color) return this.color; // It's assumed that if the input is on a
- // dark background, the user will want to
- // have a white color. If the entire app
- // is setup to be dark, then they will
- // like want to use their primary color
-
- if (this.isDark && !this.appIsDark) return 'white';else return 'primary';
- },
-
- hasError() {
- return this.internalErrorMessages.length > 0 || this.errorBucket.length > 0 || this.error;
- },
-
- // TODO: Add logic that allows the user to enable based
- // upon a good validation
- hasSuccess() {
- return this.internalSuccessMessages.length > 0 || this.success;
- },
-
- externalError() {
- return this.internalErrorMessages.length > 0 || this.error;
- },
-
- hasMessages() {
- return this.validationTarget.length > 0;
- },
-
- hasState() {
- if (this.disabled) return false;
- return this.hasSuccess || this.shouldValidate && this.hasError;
- },
-
- internalErrorMessages() {
- return this.genInternalMessages(this.errorMessages);
- },
-
- internalMessages() {
- return this.genInternalMessages(this.messages);
- },
-
- internalSuccessMessages() {
- return this.genInternalMessages(this.successMessages);
- },
-
- internalValue: {
- get() {
- return this.lazyValue;
- },
-
- set(val) {
- this.lazyValue = val;
- this.$emit('input', val);
- }
-
- },
-
- shouldValidate() {
- if (this.externalError) return true;
- if (this.isResetting) return false;
- return this.validateOnBlur ? this.hasFocused && !this.isFocused : this.hasInput || this.hasFocused;
- },
-
- validations() {
- return this.validationTarget.slice(0, Number(this.errorCount));
- },
-
- validationState() {
- if (this.disabled) return undefined;
- if (this.hasError && this.shouldValidate) return 'error';
- if (this.hasSuccess) return 'success';
- if (this.hasColor) return this.computedColor;
- return undefined;
- },
-
- validationTarget() {
- if (this.internalErrorMessages.length > 0) {
- return this.internalErrorMessages;
- } else if (this.successMessages.length > 0) {
- return this.internalSuccessMessages;
- } else if (this.messages.length > 0) {
- return this.internalMessages;
- } else if (this.shouldValidate) {
- return this.errorBucket;
- } else return [];
- }
-
- },
- watch: {
- rules: {
- handler(newVal, oldVal) {
- if (deepEqual(newVal, oldVal)) return;
- this.validate();
- },
-
- deep: true
- },
-
- internalValue() {
- // If it's the first time we're setting input,
- // mark it with hasInput
- this.hasInput = true;
- this.validateOnBlur || this.$nextTick(this.validate);
- },
-
- isFocused(val) {
- // Should not check validation
- // if disabled
- if (!val && !this.disabled) {
- this.hasFocused = true;
- this.validateOnBlur && this.$nextTick(this.validate);
- }
- },
-
- isResetting() {
- setTimeout(() => {
- this.hasInput = false;
- this.hasFocused = false;
- this.isResetting = false;
- this.validate();
- }, 0);
- },
-
- hasError(val) {
- if (this.shouldValidate) {
- this.$emit('update:error', val);
- }
- },
-
- value(val) {
- this.lazyValue = val;
- }
-
- },
-
- beforeMount() {
- this.validate();
- },
-
- created() {
- this.form && this.form.register(this);
- },
-
- beforeDestroy() {
- this.form && this.form.unregister(this);
- },
-
- methods: {
- genInternalMessages(messages) {
- if (!messages) return [];else if (Array.isArray(messages)) return messages;else return [messages];
- },
-
- /** @public */
- reset() {
- this.isResetting = true;
- this.internalValue = Array.isArray(this.internalValue) ? [] : undefined;
- },
-
- /** @public */
- resetValidation() {
- this.isResetting = true;
- },
-
- /** @public */
- validate(force = false, value) {
- const errorBucket = [];
- value = value || this.internalValue;
- if (force) this.hasInput = this.hasFocused = true;
-
- for (let index = 0; index < this.rules.length; index++) {
- const rule = this.rules[index];
- const valid = typeof rule === 'function' ? rule(value) : rule;
-
- if (valid === false || typeof valid === 'string') {
- errorBucket.push(valid || '');
- } else if (typeof valid !== 'boolean') {
- consoleError(`Rules should return a string or boolean, received '${typeof valid}' instead`, this);
- }
- }
-
- this.errorBucket = errorBucket;
- this.valid = errorBucket.length === 0;
- return this.valid;
- }
-
- }
- });
- //# sourceMappingURL=index.js.map
|