Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save lacikawiz/27f91d57e7a9267fe7d7d36aad850c7e to your computer and use it in GitHub Desktop.

Select an option

Save lacikawiz/27f91d57e7a9267fe7d7d36aad850c7e to your computer and use it in GitHub Desktop.
<Money> Svelte Component: auto-formatting number input for number entering
<p>Input with precision=2 <Money id=first bind:value=a precision=2/>
<br/>Value={a}</p>
<hr/>
<p>Input with no precision specified <Money ref:m2 bind:value=b/><br/>
Value={b}</p>
<script>
export default {
data(){return {
a:1234.34,
b:3.14159265
}},
components: {
Money : "./Money.html"
}
}
</script>
<style>
/* How to sytle the component*/
:global(#first) {
font-family:serif;
background:#ff9;
}
</style>
{
a:1234.56,
b:3.1414426
}
<div class={class} class:focused id={id} >
<label for={name} on:click="refs.inp.focus()">$</label>
<input ref:inp type="text" bind:value=rawVal name={name} on:focus="set({focused:true})" on:blur="set({focused:false})" />
</div>
<script>
export default {
data(){return {
precision:99, //default, but can be overwritten by passing in as parameter to the component
rawVal:undefined,
"class":"",
id:"",
focused:false
}},
methods: {
reformat(){
const inp=this.refs.inp
var val=inp.value
//remove non-numeric characters
var newVal=val.replace(/[^\-\.0-9]/g,"")
//remove any extra minus sign (only the front one is allowed)
if(newVal.length>1) newVal=newVal[0]+newVal.substring(1).replace(/\-/g,"")
//remove any extra dots
var posx=0
if((posx=newVal.search(/\./))>=0) newVal=newVal.substring(0,posx+1)+newVal.substring(posx+1).replace(/\./g,"")
//adding the commas
if(posx<0) posx=newVal.length
var strx=""
var ctr=-1
for(var i=posx-1;i>=0;i--){
var x=newVal[i]
if(x<="9" && x>="0"){
ctr++
if(ctr==3){
strx=","+strx
ctr=0
}
}
strx=x+strx
}
newVal=strx+newVal.substring(posx,posx+1*this.get().precision+1)
//updating the HTML input, and the data model
//inp.value=newVal
this.fRawVal=newVal //to prevent double updates
this.caretP=inp.selectionStart+(newVal.length-val.length)
if(this.caretP<0) this.caretP=0
this.set({rawVal:newVal})
//the return value is what gets converted to a number
return 1*((newVal.search(/[0-9]/)<0) ? "" : newVal.replace(/\,/g,""))
},
},
onupdate({ changed, current, previous }) {
if(changed.value && this.fValue!=this.get().value){
this.set({rawVal:current.value+""})
changed.rawVal=true //`set` inside this fn doesn't trigger another update cycle
}
if(changed.rawVal && this.fRawVal!=this.get().rawVal){
//adding a 0ms setTimout to run the code after the updates are all done
setTimeout(function(){
this.fValue=this.reformat()
this.refs.inp.selectionStart=this.caretP
this.refs.inp.selectionEnd=this.caretP
this.set({value:this.fValue})
}.bind(this),0)
}
},
oncreate() {
var x=this.get().opts
if(x && x.precision!=undefined) this.set({precision:x.precision})
},
}
</script>
<style>
div {
display: inline-flex;
background: #fff;
border:1px solid #ccc;
padding: 0.2rem;
position:relative;
}
input {
flex:1;
width:100%;
padding:0;
margin:0;
border:none;
background: transparent;
}
input:focus {
outline:none;
}
div.focused:before {
content:"";
pointer-events: none;
display:block;
box-shadow: 0px 0px 2px 1px #0000FF80;
position:absolute;
top:0px;
bottom:0px;
left:0px;
right:0px;
}
</style>
@aktxyz
Copy link

aktxyz commented May 23, 2021

any svelte 3 version of this around anywhere?

@lacikawiz
Copy link
Author

Hah! I even forgot that I made this! I need one like this too for a current project, so I'll make it into a Svelte 3 component in the next few days.

@aktxyz
Copy link

aktxyz commented May 23, 2021

I have something sort of working, but so new to svelte it's probably all wrong ... thanks !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment