user3214545
user3214545

Reputation: 2213

Angularjs: return remaining characters in textarea

I am new to Angualrjs. I am trying to display the remaining characters in a textarea.

<textarea ng-model="message" ng-maxlength="100"></textarea>
<div id="characters" ng-model="message"><span>Characters left: {{remaining()}}</span>  </div>

And this is the function:

this.scope.remaining = function() {
return this.scope.maxlength - this.scope.message.length;}

The error I am getting is:

Error: Error while interpolating: Characters left: {{remaining()}} TypeError:  this.scope is undefined

Can anyone help?

Upvotes: 6

Views: 7569

Answers (4)

tennisgent
tennisgent

Reputation: 14201

I think you're probably making this more complicated than it needs to be. Try this:

In your controller:

.controller('myCtrl', function($scope /* other dependencies here */){
    ...
    $scope.maxLength = 100; // this is the max # of chars allowed in the textarea
    ...
});

In your html:

<textarea ng-model="message" ng-maxlength="{{maxLength}}"></textarea>
<div id="characters">
    <span>Characters left: {{maxLength - message.length}}</span>
</div>

The two-way binding for {{maxLength - message.length}} will be instantly updated with the correct number of characters remaining when the user types in the textarea.

Upvotes: 19

mvvijesh
mvvijesh

Reputation: 1262

Great answer, tennisgent! However, maxLength must be interpolated in the template for the validation to kick in.

Here's a fiddle with interpolation: https://jsfiddle.net/t1fhppc9/

If the number of characters typed exceeds the value of ng-maxlength ($scope.maxLength), angular clears the bound model ($scope.message). The metric for remaining number of characters (maxLength - message.length) will no longer be valid. This can be seen in the above fiddle.

To handle this scenario, I've added a function on the scope and bound it to the template (much like user3214545's approach). This way, the max length validation would be applied on the text area, and the remaining characters metric would tell you the number of characters you've exceeded.

Template:

<div ng-controller="myCtrl">
  <textarea
    ng-model="message"
    ng-maxlength="{{ maxLength }}">
  </textarea>
  <div>
    <span>Characters left: {{ remaining() }}</span>
  </div>
  If there are more than {{ maxLength }} characters, then a red border will be shown.
  <div>
    Message: {{ message }}
  </div>
</div>

Controller:

function myCtrl($scope) {
  $scope.maxLength = 5;

  $scope.remaining = function() {
    return $scope.maxLength - angular.element(document).find('textarea')[0].value.length;
  }
}

Here' the fiddle with the function: https://jsfiddle.net/zz13p1tm/

Ofcourse, in a more realistic scenario, this would be wrapped in a directive. Both scope and element would be passed to the directive. Using isolate scope, we can also control parameters like max length, required, disabled and whether the remaining characters should be shown on the template.

Upvotes: 1

Abhishek Jain
Abhishek Jain

Reputation: 2977

I take it that this.scope.remaining is defined in the controller. Instead of using this.scope.remaining, pass $scope as a dependency and do $scope.remaining.

If you share a jsFiddle, we would be able to see exactly what the issue is.

Upvotes: 0

David Bohunek
David Bohunek

Reputation: 3201

You need to pass the scope into the function as parameter.

Upvotes: -1

Related Questions