I am trying to create a "twitter-like" character counter using Vuejs; however, I am encountering two separate issues.
- Error: Unable to get property 'length' of undefined or null reference
- 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");
}
}
});
I am trying to create a "twitter-like" character counter using Vuejs; however, I am encountering two separate issues.
- Error: Unable to get property 'length' of undefined or null reference
- 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");
}
}
});
Share
Improve this question
edited Apr 18, 2017 at 14:39
Neve12ende12
asked Apr 17, 2017 at 22:23
Neve12ende12Neve12ende12
1,1944 gold badges18 silver badges35 bronze badges
2
- 2 I answered this pretty much exact question in Vue a while back. codepen.io/Kradek/pen/VpNvxg?editors=1010 stackoverflow./q/43217239/38065 – Bert Commented Apr 17, 2017 at 22:28
-
Looks like there is a problem in your ponent. In your HTML you have the following
v-model="eligibility.address.details"
but your data attribute does not have those properties. – Maurice Commented Apr 18, 2017 at 2:05
1 Answer
Reset to default 9In general, with most modern front-end frameworks (Angular, React, Vue, etc) you want to avoid manipulating and inspecting the DOM manually. The remended 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 remendations 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 puted property that calculates the remaining characters based on that attribute.
puted: {
charactersLeft() {
var char = this.eligibility.address.details.length,
limit = 140;
return (limit - char) + " / " + limit + "characters remaining";
}
}
Then in your markup, you would use the puted property like a regular data property:
<span class="limiter">{{charactersLeft}}</span>