Mat
Mat

Reputation: 504

Update Progress Bar based on max length of input

So I'm building a form and a field within the form needs to be capped at a certain length.

I then need a simple progress bar which displays how close the user is to exceeding the maximum length on the input field. So let's say the input is capped at 50 characters. When the user hits 25 characters in the input, the progress bar should be at 50%.

I've given this a go with the below code, but I'm not sure on how to do it based on keypress or the max characters.

Something similar to what I'm after:

enter image description here

Vue Code:

Vue.component('count-fieldtype', {
    mixins: [Fieldtype],
    template: `
        <div>
            <input type="text" class="form-control type-text mb-2" placeholder="" :maxlength="max" v-model="text" />
            <small class="help-block">You have: <strong><span v-text="(max - text.length)"></span></strong> characters left.</small>
            <progress max="100" :value="calculatePercentage(value)" id="progress"></progress>
        </div>
    `,
    methods: {
        calculatePercentage(value) {
            let contentLentg = handleKeyUp();
            return 50;
        }
    },
    data: function() {
        return {
            max: 50,
            text: ''
        };
    },
});

Any help would be appreciated!

Upvotes: 1

Views: 976

Answers (3)

Emīls Gulbis
Emīls Gulbis

Reputation: 2070

You should use computed property to calculate progress https://v2.vuejs.org/v2/guide/computed.html

new Vue({
  el: "#app",
  data() {
    return {
      text: '',
      max: 150
    }
  },
  computed: {
    progress() {
      return this.text.length / this.max * 100
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<div id="app">
  <div>
    <input type="text" class="form-control type-text mb-2" placeholder="" :maxlength="max" v-model="text" />
    <small class="help-block">You have: <strong><span v-text="(max - text.length)"></span></strong> characters left.</small>
    <progress max="100" :value="progress" id="progress"></progress>
  </div>
</div>

Upvotes: 2

gere
gere

Reputation: 1730

Here is a version with some styling, if it can help. It uses too a computed property for calculating the progress bar value. (the snippet need to be run expanded).

new Vue({
  el: "#app",
  data: function() {
        return {
            max: 50,
            text: ''
        };
    },
 computed: {
   calculatePercentage() {
     let contentLength = this.text.length;
     return (contentLength / this.max) * 100;
   }
 }
})
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}
.container {
  width: 30%;
}
progress, input  {
  width: 100%;
  box-sizing: border-box;
}

progress {
  height: 8px;
  background-color: white;
  appearance: none;
 
}

progress[value]::-webkit-progress-bar {
  background-color: lightgrey;
  border-radius: 2px;
}

progress[value]::-webkit-progress-value {
  background-color: orange;
  border-radius: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="container">
  <div >
    <input type="text" class="form-control type-text mb-2" placeholder="" :maxlength="max" v-model="text" />
    
    
  </div>
  <progress max="100" :value="calculatePercentage" id="progress"></progress>
  <small class="help-block">You have: <strong><span v-text="(max - text.length)"></span></strong> characters left.</small>
  </div>
</div>

Upvotes: 2

Stephen S
Stephen S

Reputation: 3994

You might not need to check for keypress events. A computed property on the text length can be used to map the progress bar.

template: `
    <div>
        <input type="text" class="form-control type-text mb-2" placeholder="" :maxlength="max" v-model="text" />
        <small class="help-block">You have: <strong><span v-text="(max - text.length)"></span></strong> characters left.</small>
        <progress max="100" :value="progress" id="progress"></progress>
    </div>
`,
computed: {
    progress: function(){
      return Math.floor((this.text.length/this.max)*100)
    }
}

Upvotes: 2

Related Questions