Demyd Ganenko
Demyd Ganenko

Reputation: 108

Angular directive didn't update model view

I'm trying to show comments in template after clicking button in form using directive

HTML:

<h2>Comments</h2>
<ul class="comments_list">
    <li ng-repeat="com in comments" ng-cloak>{{com.name}} wrote<div class="message">{{com.text}}</div></li>
</ul>
<div class="add_comment" ng-show="posts.length > 0">
    <input type="text" class="form-control" ng-model="addComm.name" placeholder="Your name">
    <textarea class="form-control" ng-model="addComm.text" placeholder="Enter message"></textarea>
    <button class="btn btn-success" add-comment ng-model="addComm">Add</button>
</div>

And JS:

app.directive('addComment', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        priority: 1,
        link: function ($scope, element, attrs, ngModel) {
            element.on("click", function(event){
                event.preventDefault();
                console.log(ngModel.$modelValue);
                $scope.comments.push(angular.copy(ngModel.$modelValue));
            });
        }
    }
});

But after clicking "Add" in HTML my view didn't update. If I refresh the page (I'm using ngStorage) - new comment will appear in list, but not after clicking "Add" button.

Upvotes: 4

Views: 754

Answers (4)

Tharok
Tharok

Reputation: 1041

When you change model in asynchronous callback, you should encapsulate it into $apply:

$scope.$apply(function(){
    $scope.variable = true;
});

The alternative solution is to call $apply directly, after change:

$scope.variable = true;
$scope.$apply();

Upvotes: 1

Kobi Cohen
Kobi Cohen

Reputation: 678

You don't need the ngModelCtrl since the value is attached to scope already.

But what cause the problem is that you don't notify angular that the model has change, in order to do so, just call $scope.$apply

Upvotes: 3

Pratik Bhattacharya
Pratik Bhattacharya

Reputation: 3746

It's happening because you are changing the value of your $scope variable inside javascript click handler. Try this:

app.directive('addComment', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        priority: 1,
        link: function ($scope, element, attrs, ngModel) {
            element.on("click", function(event){
                event.preventDefault();
                console.log(ngModel.$modelValue);
                $scope.$apply(function() {
                     $scope.comments.push(angular.copy(ngModel.$modelValue));
               });
            });
        }
    }
});

Upvotes: 5

karaxuna
karaxuna

Reputation: 26940

You shall notify angular that something has changed:

element.on("click", function(event){
    event.preventDefault();
    console.log(ngModel.$modelValue);
    $scope.$apply(function () {
        $scope.comments.push(angular.copy(ngModel.$modelValue));
    });
});

Upvotes: 4

Related Questions