validierung
Version:
Vue composition function for form validation
2 lines (1 loc) • 13.5 kB
JavaScript
var VueDemi=function(d,a,M){if(d.install)return d;if(!a)return console.error("[vue-demi] no Vue instance found, please be sure to import `vue` before `vue-demi`."),d;if(a.version.slice(0,4)==="2.7."){let h=function(g,E){var v,R={},S={config:a.config,use:a.use.bind(a),mixin:a.mixin.bind(a),component:a.component.bind(a),provide:function(b,w){return R[b]=w,this},directive:function(b,w){return w?(a.directive(b,w),S):a.directive(b)},mount:function(b,w){return v||(v=new a(Object.assign({propsData:E},g,{provide:Object.assign(R,g.provide)})),v.$mount(b,w),v)},unmount:function(){v&&(v.$destroy(),v=void 0)}};return S};var F=h;for(var y in a)d[y]=a[y];d.isVue2=!0,d.isVue3=!1,d.install=function(){},d.Vue=a,d.Vue2=a,d.version=a.version,d.warn=a.util.warn,d.createApp=h}else if(a.version.slice(0,2)==="2.")if(M){for(var y in M)d[y]=M[y];d.isVue2=!0,d.isVue3=!1,d.install=function(){},d.Vue=a,d.Vue2=a,d.version=a.version}else console.error("[vue-demi] no VueCompositionAPI instance found, please be sure to import `@vue/composition-api` before `vue-demi`.");else if(a.version.slice(0,2)==="3."){for(var y in a)d[y]=a[y];d.isVue2=!1,d.isVue3=!0,d.install=function(){},d.Vue=a,d.Vue2=void 0,d.version=a.version,d.set=function(h,g,E){return Array.isArray(h)?(h.length=Math.max(h.length,g),h.splice(g,1,E),E):(h[g]=E,E)},d.del=function(h,g){if(Array.isArray(h)){h.splice(g,1);return}delete h[g]}}else console.error("[vue-demi] Vue version "+a.version+" is unsupported.");return d}(this.VueDemi=this.VueDemi||(typeof VueDemi!="undefined"?VueDemi:{}),this.Vue||(typeof Vue!="undefined"?Vue:void 0),this.VueCompositionAPI||(typeof VueCompositionAPI!="undefined"?VueCompositionAPI:void 0));(function(d,a){"use strict";const M=i=>i!=null,y=i=>h(i)&&!Array.isArray(i),F=i=>Array.isArray(i),h=i=>typeof i=="object"&&i!==null,g=i=>typeof(i==null?void 0:i.then)=="function";function E(i,t){for(const[e,s]of Object.entries(i))h(s)&&!(s instanceof File)&&!(s instanceof FileList)&&!(s instanceof Date)&&!(s instanceof Map)&&!(s instanceof Set)?(t[e]=F(s)?[]:{},E(s,t[e])):t[e]=s}function v(i){if(!h(i))return i;const t=F(i)?[]:{};return E(i,t),t}function R(i,t){let e=t[i[0]];for(let s=0;s<i.length;s++){const l=i[s];if(e==null)return;s>0&&(e=e[l])}return e}function S(i,t,e){if(t.length!==0){for(let s=0;s<t.length-1;s++){const l=t[s],r=t[s+1];i[l]===void 0&&(typeof r=="symbol"||Number.isNaN(+r)?i[l]={}:i[l]=[]),i=i[l]}a.isVue3?i[t[t.length-1]]=e:a.set(i,t[t.length-1],e)}}let b=1;function w(){return b++}function _(i,{wait:t}){let e=null;function s(){clearTimeout(e),e=null}function l(...r){const n=()=>{e=null,i.apply(this,r)};clearTimeout(e),e=setTimeout(n,t)}return l.cancel=s,l}class T{constructor(t){this.next=null,this.prev=null,this.value=t}}class q{constructor(){this.first=null,this.last=null,this.count=0}addFirst(t){const e=new T(t);return this.count===0?(this.first=e,this.last=e):(e.next=this.first,this.first.prev=e,this.first=e),this.count++,e}addLast(t){const e=new T(t);return this.count===0?(this.first=e,this.last=e):(e.prev=this.last,this.last.next=e,this.last=e),this.count++,e}remove(t){this.count!==0&&(t===this.first?this.removeFirst():t===this.last?this.removeLast():(t.prev.next=t.next,t.next.prev=t.prev,t.next=null,t.prev=null,this.count--))}removeFirst(){this.count!==0&&(this.count===1?(this.first=null,this.last=null,this.count--):(this.first=this.first.next,this.first.prev.next=null,this.first.prev=null,this.count--))}removeLast(){this.count!==0&&(this.count===1?(this.first=null,this.last=null,this.count--):(this.last=this.last.prev,this.last.next.prev=null,this.last.next=null,this.count--))}*[Symbol.iterator](){for(let t=this.first;t!==null;t=t.next)yield t}}class z{constructor(){this.isRacing=!1,this.assign()}cancelResolve(t){this.isRacing&&(this.isRacing=!1,this.resolve(t),this.assign())}cancelReject(t){this.isRacing&&(this.isRacing=!1,this.reject(t),this.assign())}async race(...t){this.isRacing=!0;let e;try{e=await Promise.race([this.promise,...t])}finally{this.isRacing=!1}return e}assign(){this.promise=new Promise((t,e)=>{this.resolve=t,this.reject=e})}}const G=i=>y(i)?"$value"in i:!1,$=i=>y(i)?"$uid"in i&&"$value"in i:!1;function O(i,t){for(const e of Object.values(t)){if($(e)){i.dispose(e.$uid);continue}h(e)&&O(i,e)}}function C(i,t,e,s){let l=0;for(const[r,n]of Object.entries(i)){const u=F(i)?+r-l:r,f=$(n),o=f?v(n.$value):a.unref(n);if(s({key:r,value:o,path:e}))t[u]=o;else{++l;continue}f||h(n)&&(t[u]=F(n)?[]:{},C(n,t[u],[...e,r],s))}}function J(i,t=()=>!0){const e=F(i)?[]:{};return C(i,e,[],t),e}function H(i,t,e){Object.entries(t).forEach(([s,l])=>{const r=e[s];if($(r)){i.getField(r.$uid).reset(l);return}h(l)&&H(i,l,e[s])})}class Q{constructor(){this.defaultValidationBehavior=null,this.vbfMap=new Map}getDefaultVbf(){return this.defaultValidationBehavior===null?()=>!0:this.vbfMap.get(this.defaultValidationBehavior)}}const x=new Q;function U(i){const t=x.getDefaultVbf();return i.map(e=>{if(typeof e=="function")return{vbf:t,rule:e};if(!F(e))return{vbf:t,rule:e};const[s,l,r]=e;if(typeof l=="number")return{vbf:t,rule:s,debounce:l};if(typeof s=="function")return{vbf:s,rule:l,debounce:r};const n=x.vbfMap.get(s);if(n!==void 0)return{vbf:n,rule:l,debounce:r}})}function X(i,t,e){const{$value:s,$rules:l,...r}=e,n=l?U(l):[],u=w(),f=i.registerField(u,t,s,n);return{...r,$uid:u,$value:f.modelValue,$errors:f.errors,$hasError:f.hasError,$validating:f.validating,$dirty:f.dirty,$touched:f.touched,async $validate({setTouched:o,force:c}={}){o!=null||(o=!0),c!=null||(c=!0),o&&(f.touched.value=!0),await i.validate(u,c)}}}function I(i,t){for(const[e,s]of Object.entries(t)){if(G(s)){const l=X(i,e,s);t[e]=l;continue}h(s)&&I(i,s)}}const Y=i=>typeof i=="function",W=i=>Y(i)?[i,void 0]:[i.rule,i.key];class Z{constructor(t,e,s,l,r){this.touched=a.ref(!1),this.dirty=a.ref(!1),this.rulesValidating=a.ref(0),this.validating=a.computed(()=>this.rulesValidating.value>0),this.errors=a.computed(()=>this.rawErrors.value.filter(M)),this.hasError=a.computed(()=>this.hasErrors.value.some(n=>n)),this.simpleValidators=[],this.keyedValidators=new Map,this.form=t,this.uid=e,this.name=s,this.modelValue=a.ref(l),this.rawErrors=a.ref(r.map(()=>null)),this.hasErrors=a.ref(r.map(()=>!1)),this.initialModelValue=v(this.modelValue.value),this.ruleInfos=r.map((n,u)=>{const[f,o]=W(n.rule);if(!f){o&&!this.keyedValidators.has(o)&&this.keyedValidators.set(o,[]);return}let c,p;c=p=(k,K,L=this.modelValue,B=!1)=>{if(B||this.shouldValidate(u,k,K))return this.validate(u,L)};let V,A=0,m;n.debounce&&(V=_(k=>{m(this.validate(u,k)),this.rulesValidating.value-=A,this.form.rulesValidating.value-=A,A=0},{wait:n.debounce}),c=(k,K,L=this.modelValue,B=!1)=>{if(B||this.shouldValidate(u,k,K))return++A,++this.rulesValidating.value,++this.form.rulesValidating.value,new Promise(et=>{m==null||m(),m=et,V(L)})});const j={ruleNumber:u,validator:c,validatorNotDebounced:p};if(o){const k=this.keyedValidators.get(o);k===void 0?this.keyedValidators.set(o,[j]):k.push(j)}else this.simpleValidators.push(j);return{buffer:new q,rule:f,validator:c,validatorNotDebounced:p,vbf:n.vbf,cancelDebounce:V?()=>{A=0,V.cancel(),m==null||m()}:()=>{}}}),this.watchStopHandle=this.setupWatcher()}async validate(t,e){var s;const{rule:l,buffer:r}=this.ruleInfos[t];let n;const u=a.isRef(e)?l(e.value):l(...e.map(f=>f.value));if((s=r.last)!=null&&s.value&&(r.last.value=!1,this.rulesValidating.value--,this.form.rulesValidating.value--),g(u)){const f=r.addLast(!0);this.rulesValidating.value++,this.form.rulesValidating.value++;try{n=await u}catch(o){n=o}if(r.remove(f),f.value)this.rulesValidating.value--,this.form.rulesValidating.value--,this.setError(t,n);else if(typeof n=="string"||typeof n=="symbol")throw n}else n=u,this.setError(t,n)}reset(t=this.initialModelValue){this.watchStopHandle(),this.touched.value=!1,this.dirty.value=!1,this.modelValue.value=v(t),this.rulesValidating.value=0,this.form.rulesValidating.value=0;for(let e=0;e<this.ruleInfos.length;++e){a.isVue3?(this.rawErrors.value[e]=null,this.hasErrors.value[e]=!1):(a.set(this.rawErrors.value,e,null),a.set(this.hasErrors.value,e,!1));const s=this.ruleInfos[e];if(s){s.cancelDebounce();for(const l of s.buffer)l.value=!1}}this.watchStopHandle=this.setupWatcher()}dispose(){a.isVue3&&(this.errors.effect.stop(),this.validating.effect.stop(),this.hasError.effect.stop()),this.watchStopHandle()}shouldValidateForKey(t,e,s){const l=this.keyedValidators.get(t);for(let r=0;r<l.length;++r)if(!this.shouldValidate(l[r].ruleNumber,e,s))return!1;return!0}shouldValidate(t,e,s){return this.ruleInfos[t].vbf({hasError:this.rawErrors.value[t]!==null,touched:this.touched.value,dirty:this.dirty.value,force:e,submit:s,value:this.modelValue.value})}setError(t,e){const s=typeof e=="string",l=typeof e=="symbol";if(a.isVue3){if(s)throw this.rawErrors.value[t]=e,this.hasErrors.value[t]=!0,e;if(l)throw this.hasErrors.value[t]=!0,e;this.rawErrors.value[t]=null,this.hasErrors.value[t]=!1}else{if(s)throw a.set(this.rawErrors.value,t,e),a.set(this.hasErrors.value,t,!0),e;if(l)throw a.set(this.hasErrors.value,t,!0),e;a.set(this.rawErrors.value,t,null),a.set(this.hasErrors.value,t,!1)}}setupWatcher(){return a.watch(this.modelValue,()=>{this.dirty.value=!0,this.form.validate(this.uid)},{deep:!0})}}class P extends Error{constructor(){super("One or more validation errors occurred")}}class N{constructor(){this.simpleMap=new Map,this.keyedMap=new Map,this.reactiveErrors=a.shallowReactive({}),this.rulesValidating=a.ref(0),this.submitting=a.ref(!1),this.validating=a.computed(()=>this.rulesValidating.value>0),this.hasError=a.computed(()=>this.errors.value.length>0),this.errors=a.computed(()=>Object.values(this.reactiveErrors).flatMap(t=>t.value))}registerField(t,e,s,l){const r=new Z(this,t,e,s,l),n={rollbacks:[],field:r},u=new Set;for(let f=0;f<l.length;++f){const o=W(l[f].rule)[1];if(o===void 0)continue;let c=this.keyedMap.get(o);c===void 0?this.keyedMap.set(o,{fields:[r],modelValues:[r.modelValue]}):u.has(o)||(c.fields.push(r),c.modelValues.push(r.modelValue)),c=this.keyedMap.get(o),u.add(o);const p=()=>{for(let V=0;V<c.fields.length;++V)if(c.fields[V]===r){c.fields.splice(V,1),c.modelValues.splice(V,1);break}c.fields.length===0&&this.keyedMap.delete(o)};n.rollbacks.push(p)}return this.simpleMap.set(t,n),a.isVue3?this.reactiveErrors[t]=r.errors:a.set(this.reactiveErrors,t,r.errors),r}validate(t,e=!1){const{field:s}=this.simpleMap.get(t);return Promise.allSettled([...s.simpleValidators.map(({validator:l})=>l(e,!1)),...this.collectValidatorResultsForKeys(s,e,!1)])}async validateAll(t){const e=await Promise.allSettled(this.collectValidatorResultsForNames(t));for(let s=0;s<e.length;++s)if(e[s].status==="rejected")throw new P}dispose(t){const e=this.simpleMap.get(t);e&&(e.field.dispose(),e.rollbacks.forEach(s=>s())),this.simpleMap.delete(t),a.isVue3?delete this.reactiveErrors[t]:a.del(this.reactiveErrors,t)}resetFields(){for(const{field:t}of this.simpleMap.values())t.reset()}getField(t){const e=this.simpleMap.get(t);return e==null?void 0:e.field}*collectValidatorResultsForKeys(t,e,s,l=t.keyedValidators.keys()){for(const r of l){const{fields:n,modelValues:u}=this.keyedMap.get(r);if(!(this.isEveryOtherFieldTouched(t,n)&&t.shouldValidateForKey(r,e,s)))return;for(let o=0;o<n.length;++o){const c=n[o].keyedValidators.get(r);for(let p=0;p<c.length;++p)yield s?c[p].validatorNotDebounced(e,s,u,n[p]===t):c[p].validator(e,s,u,n[p]===t)}}}*collectValidatorResultsForNames(t){if(t===void 0){for(const{field:l}of this.simpleMap.values()){l.touched.value=!0;for(let r=0;r<l.simpleValidators.length;++r)yield l.simpleValidators[r].validatorNotDebounced(!1,!0)}for(const[l,{fields:r,modelValues:n}]of this.keyedMap.entries())for(let u=0;u<r.length;++u){const f=r[u].keyedValidators.get(l);for(let o=0;o<f.length;++o)yield f[o].validatorNotDebounced(!1,!0,n)}return}if(t.length===0)return;const e=new Set(t),s=new Set;for(const{field:l}of this.simpleMap.values())e.has(l.name)&&(l.touched.value=!0);for(const{field:l}of this.simpleMap.values())if(e.has(l.name)){for(let r=0;r<l.simpleValidators.length;++r)yield l.simpleValidators[r].validatorNotDebounced(!1,!0);for(const r of l.keyedValidators.keys())s.has(r)||(s.add(r),yield*this.collectValidatorResultsForKeys(l,!1,!0,[r]))}}isEveryOtherFieldTouched(t,e){for(let s=0;s<e.length;++s)if(t!==e[s]&&!e[s].touched.value)return!1;return!0}}function D(i){const t=new N,e=new z;I(t,i);const s=a.reactive(i);return{form:s,submitting:t.submitting,validating:t.validating,hasError:t.hasError,errors:t.errors,async validateFields({names:l,predicate:r}={}){t.submitting.value=!0;const n=J(s,r);try{await e.race(t.validateAll(l))}finally{t.submitting.value=!1}return n},resetFields(l){e.cancelReject(new P),l===void 0?t.resetFields():H(t,l,s)},add(l,r){const n=l[l.length-1];if(n!==void 0){const u={[n]:r};I(t,u);let f=u[n];const o=R(l,s);a.isVue2&&(f=a.reactive(f)),Array.isArray(o)?o.push(f):S(s,l,f)}},remove(l){const r=l.pop();if(r!==void 0)if(l.length===0)O(t,s[r]),a.isVue3?delete s[r]:a.del(s,r);else{const n=R(l,s);if(Array.isArray(n)){const u=n.splice(+r,1);O(t,u)}else O(t,n[r]),a.isVue3?delete n[r]:a.del(n,r)}}}}function tt(i){return{install(){var t;for(const[e,s]of Object.entries((t=i.validationBehavior)!=null?t:{}))x.vbfMap.set(e,s);x.vbfMap.has(i.defaultValidationBehavior)&&(x.defaultValidationBehavior=i.defaultValidationBehavior)}}}d.ValidationError=P,d.createValidation=tt,d.useValidation=D})(this.Validierung=this.Validierung||{},VueDemi);