The basic validation directives such as ng-minlength will block ngModel from being updated until validation is passed. It's not a bug as such, and it's useful in many cases, but it can also be less than useful in some cases. Such as this.
The way around this while still keeping the benefits of using ngModel based validation (including form validity etc) is to set the validation step 'manually' by using $setValidity. To do this you would remove the ng-minlength attribute and use an ng-change callback.
You will also need to make sure that your form element is named and part of a named form, in order to get access to the relevant ngModelController.
<form name="formCtrl">
<textarea ng-trim="false"
ng-model="form.text"
ng-change="checkTextLength()"
name="formText">
</textarea>
<p>{{240 - form.text.length}} left</p>
</form>
And then in your controller, assuming you are just using $scope here:
$scope.checkTextLength = function(){
if($scope.form.text.length < 20){
$scope.formCtrl.formText.$setValidity('minlength', false);
} else{
$scope.formCtrl.formText.$setValidity('minlength', true);
}
if($scope.form.text.length > 240){
$scope.formCtrl.formText.$setValidity('maxlength', false);
} else{
$scope.formCtrl.formText.$setValidity('maxlength', true);
}
}
I forked your codepen to create a working example here. There I also added a bit to the template to show the validity state.