Himmators
Himmators

Reputation: 15006

How to listen for changes in textarea from directive?

I have a textarea that looks like this:

    <textarea ng-controller="text" autoexpand id="tasks" ng-focus="uncheckAll()" ng-change="processText()" ng-model="tasks.tasks"></textarea>

The directive autoexpand is adding rows to the textarea based on how many lines you write. (it has nowrap set in css)

//adding rows to the textarea based on the number of newlines.
directive('autoexpand', function($timeout){
    function expand(element){
        var count = element.val().split('\n').length+1;
        element.attr('rows', count)
    }
    return {
        restrict: 'A',
        require: '?ngModel',
        link: function(scope, element){
        //onload
        $timeout(function(){
            expand(element);
        });
        element.on('keydown', function (){
                console.log('change')
                expand(element)
            });
        }

    }
}).

This works when I update the textarea by writing to it, but sometimes, It's updated from the model. How can I run expand() also in that case (I tried element.on('change'..., element.change( and element.bind('change' but it doesn't seem to trigger at all

Upvotes: 0

Views: 2099

Answers (3)

Jerrad
Jerrad

Reputation: 5290

You want to listen to and react to the model (instead of the element) whenever possible. You can have a $watch in the directive that will fire whenever the model changes (regardless of how it changes):

scope.$watch(attrs.ngModel, function(){
    expand(element);
});

You don't even need the keydown event handler anymore. The only other thing you need to do is add ng-trim="false" to the text area. Otherwise, the model will ignore whitespace (including any new lines that you type).

Demo

Upvotes: 0

b0nyb0y
b0nyb0y

Reputation: 1446

You should be listening for change on ngModel this way:

// here "model" is linked to ng-model property
scope.$watch("model", function() {
   console.log("Changed");
   expand(element);
});

Though you can certainly watch 'tasks.tasks', it will be limiting the usefulness of your directive to just one use case.

Upvotes: 1

Mathew Berg
Mathew Berg

Reputation: 28750

you can listen in on ngModel changes by doing somethign like this:

scope.$on("ngModel", function(){
    //this will fire when ng model changes
}, true);

Upvotes: 0

Related Questions