Abhishek Bansal
Abhishek Bansal

Reputation: 5335

Changing ngModel value programatically from controller

I wish to modify value of an ngModel variable from my controller. However it doesn't seem to be reflecting in views. I have seen few other questions on SO but none worked for me. I want a solution where I do not need to create a new directive for this. I have also tried to wrap the change in $scope.$apply without success.

Here is plunkr demonstrating the issue.

Here is code from plunkr

JavaScript Controller:

    app.controller('MainCtrl', function($scope) {
  $scope.Attachment = "something"
  $scope.change = function () {
      $scope.$apply(function() {
          $scope.Attachment = "otherthing";
      });
}

HTML:

<body ng-controller="MainCtrl">
    <section class="content" ng-app="offer">
        <div>
            <button name="change" ng-click="change()" ng-model="Attachment">change</button>
            <!-- <input name="Attachment" type="file" class="file_up" onchange="angular.element(this).scope().change(this)" ng-model="Attachment" /> -->
            <span>{{Attachment}}</span>

        </div>
    </section>
</body>

Upvotes: 3

Views: 9334

Answers (4)

bosch
bosch

Reputation: 1129

It's a best practice to bind to object properties instead of primitive types.
You are binding to a string which is a primitive type and is immutable.
You should also remove the $apply as it is not necessary since you are under the angular hood so it will perform the $apply automatically.

If you add your data as a property of an object you will not lose the reference anymore:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  //this has changed:
  $scope.data = {
    Attachment: "something"
  }

  $scope.change = function() {
    //and $apply was removed from here
    $scope.data.Attachment = "otherthing";
  }
});

and in the html you just need to change:

<span>{{data.Attachment}}</span>

EDIT: although some other answers are correct, I thought you should see what's a best practice for binding. The updated plunker here.

Upvotes: 3

colin moore
colin moore

Reputation: 41

You shouldn't need to use $scope.$apply(). I made this change to the plunkr to get the view to update.

app.controller('MainCtrl', function($scope) {
  $scope.Attachment = "something"
  $scope.change = function () {
      $scope.Attachment = "other";
  }
});

Upvotes: 1

Shekhar Khairnar
Shekhar Khairnar

Reputation: 2691

Check this one may help you

function MyController($scope) {

  $scope.Attachment = "something"
  $scope.change = function() {

    $scope.Attachment = "otherthing";

  }
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>

<div ng-app ng-controller="MyController">
  <button name="change" ng-click="change()" ng-model="Attachment">change</button>

  <span>{{Attachment}}</span>
</div>

Upvotes: 1

sma
sma

Reputation: 9597

Remove the ng-model from the button and remove the $scope.$apply from the change handler:

http://plnkr.co/edit/lOyoTBxs0L0hMs20juLS?p=preview

Upvotes: 3

Related Questions