Move VeeValidate calls to own components and config

This commit is contained in:
Ramon Wenger 2021-12-21 13:11:34 +01:00
parent 93938baa34
commit b37abd3d16
6 changed files with 126 additions and 53 deletions

View File

@ -66,7 +66,9 @@ const devWebpackConfig = merge(baseWebpackConfig, {
},
],
}),
new BundleAnalyzerPlugin(),
new BundleAnalyzerPlugin({
generateStatsFile: true
}),
],
});

View File

@ -0,0 +1,89 @@
<template>
<ValidationProvider
v-slot="{errors}"
:name="name"
:rules="rules"
>
<div class="skillboxform-input">
<label
:for="id"
class="skillboxform-input__label">{{ label }}</label>
<input
:value="value"
:class="{ 'skillboxform-input__input--error': errors.length }"
v-bind="$attrs"
:id="id"
class="change-form__email skillbox-input skillboxform-input__input"
autocomplete="off"
@input="$emit('input', $event.target.value)"
>
<small
:data-cy="localErrorsCy"
class="skillboxform-input__error"
v-if="errors.length"
>{{ errors[0] }}</small>
<small
:key="error"
:data-cy="remoteErrorsCy"
class="skillboxform-input__error"
v-for="error in remoteErrors"
>{{ error }}</small>
</div>
</ValidationProvider>
</template>
<script>
const {ValidationProvider} = () => import('vee-validate');
const {configureValidation} = () => import('@/validation');
// todo: use this in beta-login, license-activation and PasswordChangeForm
export default {
props: {
value: {
type: String,
default: '',
},
remoteErrors: {
type: Array,
default: undefined,
},
name: {
type: String,
default: '',
},
label: {
type: String,
default: '',
},
rules: {
type: String,
default: 'required',
},
},
components: {
ValidationProvider,
},
inheritAttrs: false,
computed: {
id() {
return this.$attrs.id || this._uid;
},
remoteErrorsCy() {
return `${this.name}-remote-errors`;
},
localErrorsCy() {
return `${this.name}-local-errors`;
},
},
mounted() {
configureValidation();
},
};
</script>
<style scoped lang="scss">
@import '~styles/helpers';
</style>

View File

@ -7,8 +7,6 @@ import App from './App';
import {router, postLoginRedirectUrlKey} from './router';
import store from '@/store/index';
import VueScrollTo from 'vue-scrollto';
import {extend, localize} from 'vee-validate';
import {required, min, double, confirmed} from 'vee-validate/dist/rules';
import {dateFilter, dateTimeFilter} from './filters/date-filter';
import autoGrow from '@/directives/auto-grow';
import clickOutside from '@/directives/click-outside';
@ -18,7 +16,6 @@ import VueRemoveEdges from '@/plugins/edges';
import VueMatomo from 'vue-matomo';
import VueToast from 'vue-toast-notification';
import VueLogger from 'vuejs-logger';
import de from 'vee-validate/dist/locale/de.json';
Vue.config.productionTip = false;
const isProduction = process.env.NODE_ENV === 'production';
@ -62,51 +59,6 @@ const apolloProvider = new VueApollo({
defaultClient: privateApolloClient
});
extend('required', required);
extend('min', min);
extend('decimal', double);
extend('confirmed', confirmed);
// const dict = {
// custom: {
// oldPassword: {
// required: 'Dein aktuelles Passwort fehlt'
// },
// newPassword: {
// required: 'Dein neues Passwort fehlt',
// min: 'Das neue Passwort muss mindestens 8 Zeichen lang sein'
// }
// }
// };
localize('de', {
de: {
...de,
names: {
password: 'Password',
email: 'E-Mail',
coupon: 'Coupon'
}
}
});
// https://github.com/baianat/vee-validate/issues/51
extend('strongPassword', {
getMessage: field => 'Das Passwort muss Grossbuchstaben, Zahlen und Sonderzeichen beinhalten und mindestens 8 Zeichen lang sein',
validate: value => {
const strongRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*?(),.":{}|<>+])(?=.{8,})/;
return strongRegex.test(value);
}
});
extend('email', {
getMessage: field => 'Bitte geben Sie eine gülitge E-Mail an',
validate: value => {
const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/;
return emailRegex.test(value);
}
});
Vue.filter('date', dateFilter);
Vue.filter('datetime', dateTimeFilter);

View File

@ -48,8 +48,9 @@
<script>
import BETA_LOGIN_MUTATION from '@/graphql/gql/mutations/betaLogin.gql';
import {ValidationObserver, ValidationProvider} from 'vee-validate';
import ValidatedInput from '@/components/validation/ValidatedInput';
const {ValidationObserver, ValidationProvider} = () => import('vee-validate');
const ValidatedInput = () => import('@/components/validation/ValidatedInput');
const {configureValidation} = () => import('@/validation');
export default {
components: {
@ -69,6 +70,10 @@
};
},
mounted() {
configureValidation();
},
methods: {
validateBeforeSubmit() {
this.submitted = true;

View File

@ -59,13 +59,14 @@
import REDEEM_COUPON from '@/graphql/gql/mutations/redeemCoupon.gql';
import ME_QUERY from '@/graphql/gql/queries/meQuery.gql';
import LoadingButton from '@/components/LoadingButton';
import ValidatedInput from '@/components/validation/ValidatedInput';
import {ValidationObserver} from 'vee-validate';
import me from '@/mixins/me';
import logout from '@/mixins/logout';
import pageTitleMixin from '@/mixins/page-title';
const ValidatedInput = () => import('@/components/validation/ValidatedInput');
const {ValidationObserver} = () => import('vee-validate');
export default {
mixins: [me, logout, pageTitleMixin],
components: {

View File

@ -0,0 +1,24 @@
import {extend, localize} from 'vee-validate';
import {confirmed, double, email, min, required} from 'vee-validate/dist/rules';
import de from 'vee-validate/dist/locale/de.json';
export const configureValidation = () => {
console.log('configuring validation');
extend('required', required);
extend('min', min);
extend('decimal', double);
extend('confirmed', confirmed);
extend('email', email);
localize('de', {
de: {
...de,
names: {
password: 'Password',
email: 'E-Mail',
coupon: 'Coupon',
},
},
});
};