Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vuejs: Character Counter

I am trying to create a "twitter-like" character counter using Vuejs; however, I am encountering two separate issues.

  1. Error: Unable to get property 'length' of undefined or null reference
  2. Even if I get it to work, is there any way to call the same function using multiple events without adding each one as a separate call to the tag. Ex: v-on:keyup,blur,focus="limiter(this,140)"

HTML:

<div class="form-group" id="vue">
  <label for="eligibility-address-detail">Address Notes:</label>
  <textarea class="form-control" id="eligibility-address-detail" rows="3" 
   name="eligibility[address][detail]" v-model="eligibility.address.details" 
   v-on:keyup="limiter(this, 140)" required></textarea>
  <span class="limiter"></span>
</div>

JavaScript:

var main = new Vue({
  el: "#vue",
  data: {
    eligibility: {
      address: {
        details: ""
      }
    }       
  },
  methods: {        
      limit: function(elem, limit){
          var chars = elem.value.length;
          if (chars > limit) {
              elem.value = elem.value.substr(0, limit);
              chars = limit;
          }
          $(elem).siblings('.limiter').html((limit - chars) + " / " + limit + "characters remaining");
      }
  }
});
like image 286
Neve12ende12 Avatar asked Apr 17 '17 22:04

Neve12ende12


1 Answers

In general, with most modern front-end frameworks (Angular, React, Vue, etc) you want to avoid manipulating and inspecting the DOM manually. The recommended approach is to make everything data-driven (aka: use the model) and let the framework update the DOM when needed - this is a key concept behind the whole "reactivity system"

But here are a few recommendations to fix your issue:

Do not call your limit() method on DOM events. Instead... look at the eligibility.address.details attribute which is are binding to the inputs v-model.

You can create a computed property that calculates the remaining characters based on that attribute.

computed: {
    charactersLeft() {
        var char = this.eligibility.address.details.length,
            limit = 140;

        return (limit - char) + " / " + limit + "characters remaining";
      }
}

Then in your markup, you would use the computed property like a regular data property:

<span class="limiter">{{charactersLeft}}</span>
like image 91
Maurice Avatar answered Nov 02 '22 19:11

Maurice