Open loihp opened 7 months ago
You can see that via v-model and can pass value. or use model-value to pass value to component
Vuetify can't handle your logic. this is just component and you have to implement it correctly.
You can see that via v-model and can pass value. or use model-value to pass value to component
Vuetify can't handle your logic. this is just component and you have to implement it correctly.
i really know that! what i want is somthing like autocomplete="one-time-code"
I'm experiencing this as well on iOS.
Reproduction will require getting a mobile device to receive an OTP text message which the operating system then displays as an autofill shortcut on the keyboard.
Say I received a text with a 6-digit OTP that my phone presented to me on my device's keyboard.
Tapping that autofill shortcut should put a digit in each text field
Only the first text field is modified with only the first digit (or maybe all 6, it's hard to tell)
I see. right now this makes sense and more clear. thanks
@websitevirtuoso I'm experiencing this as well, is it resolved?
It seems that this is related to ios not calling on paste:
It looks like this was fixed at some point in the past, but the fix was lost. Between a repo rename and converting to v3 there are too many changes to track down when exactly this broke.
OG commit to support this feature: https://github.com/vuetifyjs/vuetify/commit/8c67ed8cf96334a86c6f087b7abfa845992098a2
The issue is the maxlength="1"
prop on each of the <input>
elements. iOS fires a textInput
event with data: '12345'
unlike a human typing who types a single character a time. I am working on a complete fix with correct focus handling, but in the meantime I used patch-package with the following patch:
patches/vuetify+3.5.9.patch
:
diff --git a/node_modules/vuetify/dist/vuetify.esm.js b/node_modules/vuetify/dist/vuetify.esm.js
index 4e635a0..1e20d68 100644
--- a/node_modules/vuetify/dist/vuetify.esm.js
+++ b/node_modules/vuetify/dist/vuetify.esm.js
@@ -23167,7 +23167,6 @@ const VOtpInput = genericComponent()({
"disabled": props.disabled,
"inputmode": props.type === 'number' ? 'numeric' : 'text',
"min": props.type === 'number' ? 0 : undefined,
- "maxlength": "1",
"placeholder": props.placeholder,
"type": props.type === 'number' ? 'text' : props.type,
"value": model.value[i],
diff --git a/node_modules/vuetify/dist/vuetify.js b/node_modules/vuetify/dist/vuetify.js
index 0164850..67da61c 100644
--- a/node_modules/vuetify/dist/vuetify.js
+++ b/node_modules/vuetify/dist/vuetify.js
@@ -23171,7 +23171,6 @@
"disabled": props.disabled,
"inputmode": props.type === 'number' ? 'numeric' : 'text',
"min": props.type === 'number' ? 0 : undefined,
- "maxlength": "1",
"placeholder": props.placeholder,
"type": props.type === 'number' ? 'text' : props.type,
"value": model.value[i],
diff --git a/node_modules/vuetify/dist/vuetify.min.js b/node_modules/vuetify/dist/vuetify.min.js
index 04f4bce..8ff2b04 100644
--- a/node_modules/vuetify/dist/vuetify.min.js
+++ b/node_modules/vuetify/dist/vuetify.min.js
@@ -1796,7 +1796,7 @@ t[f.value]=a
let l=null
f.value>c.value.length?l=c.value.length+1:f.value+1!==v.value&&(l="next"),c.value=t,l&&ee(m.value,l)}function b(e){const t=c.value.slice(),a=f.value
let l=null;["ArrowLeft","ArrowRight","Backspace","Delete"].includes(e.key)&&(e.preventDefault(),"ArrowLeft"===e.key?l="prev":"ArrowRight"===e.key?l="next":["Backspace","Delete"].includes(e.key)&&(t[f.value]="",c.value=t,f.value>0&&"Backspace"===e.key?l="prev":requestAnimationFrame((()=>{g.value[a]?.select()}))),requestAnimationFrame((()=>{null!=l&&ee(m.value,l)})))}function V(){u(),f.value=-1}return vt({VField:{color:t.computed((()=>e.color)),bgColor:t.computed((()=>e.color)),baseColor:t.computed((()=>e.baseColor)),disabled:t.computed((()=>e.disabled)),error:t.computed((()=>e.error)),variant:t.computed((()=>e.variant))}},{scoped:!0}),t.watch(c,(e=>{e.length===v.value&&o("finish",e.join(""))}),{deep:!0}),t.watch(f,(e=>{e<0||t.nextTick((()=>{g.value[e]?.select()}))})),At((()=>{const[a,o]=R(l)
-return t.createVNode("div",t.mergeProps({class:["v-otp-input",{"v-otp-input--divided":!!e.divider},e.class],style:[e.style]},a),[t.createVNode("div",{ref:m,class:"v-otp-input__content",style:[r.value]},[p.value.map(((a,l)=>t.createVNode(t.Fragment,null,[e.divider&&0!==l&&t.createVNode("span",{class:"v-otp-input__divider"},[e.divider]),t.createVNode(ti,{focused:i.value&&e.focusAll||f.value===l,key:l},{...n,loader:void 0,default:()=>t.createVNode("input",{ref:e=>g.value[l]=e,"aria-label":d(e.label,l+1),autofocus:0===l&&e.autofocus,autocomplete:"one-time-code",class:["v-otp-input__field"],disabled:e.disabled,inputmode:"number"===e.type?"numeric":"text",min:"number"===e.type?0:void 0,maxlength:"1",placeholder:e.placeholder,type:"number"===e.type?"text":e.type,value:c.value[l],onInput:y,onFocus:e=>{return t=l,s(),void(f.value=t)
+return t.createVNode("div",t.mergeProps({class:["v-otp-input",{"v-otp-input--divided":!!e.divider},e.class],style:[e.style]},a),[t.createVNode("div",{ref:m,class:"v-otp-input__content",style:[r.value]},[p.value.map(((a,l)=>t.createVNode(t.Fragment,null,[e.divider&&0!==l&&t.createVNode("span",{class:"v-otp-input__divider"},[e.divider]),t.createVNode(ti,{focused:i.value&&e.focusAll||f.value===l,key:l},{...n,loader:void 0,default:()=>t.createVNode("input",{ref:e=>g.value[l]=e,"aria-label":d(e.label,l+1),autofocus:0===l&&e.autofocus,autocomplete:"one-time-code",class:["v-otp-input__field"],disabled:e.disabled,inputmode:"number"===e.type?"numeric":"text",min:"number"===e.type?0:void 0,placeholder:e.placeholder,type:"number"===e.type?"text":e.type,value:c.value[l],onInput:y,onFocus:e=>{return t=l,s(),void(f.value=t)
var t},onBlur:V,onKeydown:b,onPaste:e=>{return t=l,(a=e).preventDefault(),a.stopPropagation(),c.value=(a?.clipboardData?.getData("Text")??"").split(""),void g.value?.[t].blur()
var t,a}},null)})]))),t.createVNode("input",t.mergeProps({class:"v-otp-input-input",type:"hidden"},o,{value:c.value.join("")}),null),t.createVNode(Hr,{contained:!0,"content-class":"v-otp-input__loader","model-value":!!e.loading,persistent:!0},{default:()=>[n.loader?.()??t.createVNode(Hl,{color:"boolean"==typeof e.loading?void 0:e.loading,indeterminate:!0,size:"24",width:"2"},null)]}),n.default?.()])])})),{blur:()=>{g.value?.some((e=>e.blur()))},focus:()=>{g.value?.[0].focus()},reset:function(){c.value=[]},isFocused:i}}})
const rv=a({scale:{type:[Number,String],default:.5},...l()},"VParallax"),iv=gt()({name:"VParallax",props:rv(),setup(e,a){let{slots:l}=a
diff --git a/node_modules/vuetify/lib/components/VOtpInput/VOtpInput.mjs b/node_modules/vuetify/lib/components/VOtpInput/VOtpInput.mjs
index ce0a7d0..f29f80f 100644
--- a/node_modules/vuetify/lib/components/VOtpInput/VOtpInput.mjs
+++ b/node_modules/vuetify/lib/components/VOtpInput/VOtpInput.mjs
@@ -188,7 +188,6 @@ export const VOtpInput = genericComponent()({
"disabled": props.disabled,
"inputmode": props.type === 'number' ? 'numeric' : 'text',
"min": props.type === 'number' ? 0 : undefined,
- "maxlength": "1",
"placeholder": props.placeholder,
"type": props.type === 'number' ? 'text' : props.type,
"value": model.value[i],
Has this problem been fixed in any updates ?
Any update? We're quite dependant on the OTP component, and this renders it quite useless. Confirmed still an issue with 3.6.7
Environment
Vuetify Version: 3.4.0 Vue Version: 3.0.0 Browsers: Chrome 119.0.0.0 OS: Android, iOS
Steps to reproduce
I use v-otp-input to get otp from user
Expected Behavior
On mobile device when receive sms otp keyboard on mobile device auto showing and when click this auto fill to otp input
Actual Behavior
Fill first input like picture i attached
Reproduction Link
https://play.vuetifyjs.com/#...