JSFiddle - React, Tailwind, and code Playground

by dkrotts

HTML

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<!doctype html>
<html>
    <head></head>
<body ng-controller="foo">
    <div>
        <textarea my-maxlength="20" ng-model="foo"></textarea>
        <h1>{{foo}}</h1>
        <button ng-click="test()">TEST</button>
    </div>
    
    <div>
        <textarea my-maxlength="40" ng-model="bar"></textarea>
        <h1>{{bar}}</h1>
        <button ng-click="test2()">TEST</button>
    </div>        
</body>
</html>

JavaScript

var myApp = angular.module('myApp', []);
angular.element(document).ready(function() {
   angular.bootstrap(document, ['myApp']);
});

function foo($scope) {
    $scope.test = function() {
        console.log($scope.foo);
    }      
    $scope.test2 = function() {
         console.log($scope.bar);
    }        
}

myApp.directive('myMaxlength', ['$compile', '$timeout', function($compile, $timeout) {
    return {
        restrict: 'A',
        require: '?ngModel',
        scope: false,
        link: function (scope, element, attrs, controller) {
            var counterElement = $compile(angular.element('<span>Characters remaining: {{charsRemaining}}</span>'))(scope);

            element.parent().append(counterElement);

            scope.charsRemaining = parseInt(attrs.myMaxlength);

            scope.onEdit = function() {
                scope.$apply(read);
            }

            element.bind('keyup keydown focus input paste', scope.onEdit);

            var read = function() {
                var maxLength = parseInt(attrs.myMaxlength),
                    currentLength = parseInt(element.val().length);

                if (currentLength >= maxLength) {
                    element.val(element.val().substr(0, maxLength));
                    scope.charsRemaining = 0;
                } else {
                    scope.charsRemaining = maxLength - currentLength;
                }

                if (controller) {
                    $timeout(function() {
                        controller.$setViewValue(element.val());
                    });
                }
            }
        }
    }
}]);