Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ng-model does not update controller value

People also ask

What is the difference between ng-model and ngModel?

They are interchangeable in the code. No. You can use ng-model with AngularJS and [(ngModel)] with Angular (v2+). It depends on which one you want to use.

Is NG-model a directive?

ngModel is a directive which binds input, select and textarea, and stores the required user value in a variable and we can use that variable whenever we require that value. It also is used during validations in a form.

Can we use filter in NG-model?

The ng-repeat values can be filtered according to the ng-model in AngularJS by using the value of the input field as an expression in a filter. We can set the ng-model directive on an input field to filter ng-repeat values.


"If you use ng-model, you have to have a dot in there."
Make your model point to an object.property and you'll be good to go.

Controller

$scope.formData = {};
$scope.check = function () {
  console.log($scope.formData.searchText.$modelValue); //works
}

Template

<input ng-model="formData.searchText"/>
<button ng-click="check()">Check!</button>

This happens when child scopes are in play - like child routes or ng-repeats. The child-scope creates it's own value and a name conflict is born as illustrated here:

See this video clip for more: https://www.youtube.com/watch?v=SBwoFkRjZvE&t=3m15s


Controller as version (recommended)

Here the template

<div ng-app="example" ng-controller="myController as $ctrl">
    <input type="text" ng-model="$ctrl.searchText" />
    <button ng-click="$ctrl.check()">Check!</button>
    {{ $ctrl.searchText }}
</div>

The JS

angular.module('example', [])
  .controller('myController', function() {
    var vm = this;
    vm.check = function () {
      console.log(vm.searchText);
    };
  });

An example: http://codepen.io/Damax/pen/rjawoO

The best will be to use component with Angular 2.x or Angular 1.5 or upper

########

Old way (NOT recommended)

This is NOT recommended because a string is a primitive, highly recommended to use an object instead

Try this in your markup

<input type="text" ng-model="searchText" />
<button ng-click="check(searchText)">Check!</button>
{{ searchText }}

and this in your controller

$scope.check = function (searchText) {
    console.log(searchText);
}

In Mastering Web Application Development with AngularJS book p.19, it is written that

Avoid direct bindings to scope's properties. Two-way data binding to object's properties (exposed on a scope) is a preferred approach. As a rule of thumb, you should have a dot in an expression provided to the ng-model directive (for example, ng-model="thing.name").

Scopes are just JavaScript objects, and they mimic dom hierarchy. According to JavaScript Prototype Inheritance, scopes properties are separated through scopes. To avoid this, dot notation should use to bind ng-models.


Using this instead of $scope works.

function AppCtrl($scope){
  $scope.searchText = "";
  $scope.check = function () {
    console.log("You typed '" + this.searchText + "'"); // used 'this' instead of $scope
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app>
  <div ng-controller="AppCtrl">
    <input ng-model="searchText"/>
    <button ng-click="check()">Write console log</button>
  </div>
</div>

Edit: At the time writing this answer, I had much more complicated situation than this. After the comments, I tried to reproduce it to understand why it works, but no luck. I think somehow (don't really know why) a new child scope is generated and this refers to that scope. But if $scope is used, it actually refers to the parent $scope because of javascript's lexical scope feature.

Would be great if someone having this problem tests this way and inform us.


I had the same problem and it was due to me not declaring the blank object first at the top of my controller:

$scope.model = {}

<input ng-model="model.firstProperty">

Hope this will works for you!


I came across the same issue when dealing with a non-trivial view (there are nested scopes). And finally discovered this is a known tricky thing when developing AngularJS application due to the nature of prototype-based inheritance of java-script. AngularJS nested scopes are created through this mechanism. And value created from ng-model is placed in children scope, not saying parent scope (maybe the one injected into controller) won't see the value, the value will also shadow any property with same name defined in parent scope if not use dot to enforce a prototype reference access. For more details, checkout the online video specific to illustrate this issue, http://egghead.io/video/angularjs-the-dot/ and comments following up it.


Have a look at this fiddle http://jsfiddle.net/ganarajpr/MSjqL/

I have ( I assume! ) done exactly what you were doing and it seems to be working. Can you check what is not working here for you?