9

Related Post, but didn't help: Scoping issue when setting ngModel from a directive

EDIT: Can I use ng-model with isolated scope? didn't work either.

I got the some problem but in a more complex way I guess. I want to write a pulldown that does not use any input for data saving. I'd rather have the ngModel to take care of it.

http://jsfiddle.net/QeM6g/6/

The jsFiddle example above shows a demo where the above described methods didn't work.

// this is what should work but doesn't
ngModel.$setViewValue(value);
scope.$apply(attr.ngModel,value);

For some reason the scope of the ngModelController is a sibling of my scope. so it doesn't pass the changes back to the parent. at least all other sibling scopes behave as you'd expect. i.e. ng-change works in combination.

Cœur
  • 37,241
  • 25
  • 195
  • 267

2 Answers2

23

Angularjs doesn't deal very well with direct bindings to primitive types.

If you change this line:

$scope.productId = 16;

to something like this:

$scope.selectedProduct = {
    id: 16
}

and change those references on the rest of the code, you should be able to overcome the issue.

jsFiddle: http://jsfiddle.net/M2cL7/

bmleite
  • 26,850
  • 4
  • 71
  • 46
  • Thanks, I would have never guessed that. Saved me a sleepless nights. I reported this as [issue here](https://github.com/angular/angular.js/issues/1913) for all who want to know if that behavior will be fixed. – Richard Burkhardt Jan 29 '13 at 16:10
  • @bmleite Its not a problem with angular's data binding. Its about javascript prototyping. Please read https://github.com/angular/angular.js/wiki/Understanding-Scopes – Vivek Nov 24 '15 at 11:19
7

Don't bind to primitives in a scope, bind to an object in the scope.

From https://github.com/angular/angular.js/wiki/Understanding-Scopes

... until you try 2-way data binding (i.e., form elements, ng-model) to a primitive (e.g., number, string, boolean) defined on the parent scope from inside the child scope. It doesn't work the way most people expect it should work. What happens is that the child scope gets its own property that hides/shadows the parent property of the same name. This is not something AngularJS is doing – this is how JavaScript prototypal inheritance works. New AngularJS developers often do not realize that ng-repeat, ng-switch, ng-view and ng-include all create new child scopes, so the problem often shows up when these directives are involved.

This issue with primitives can be easily avoided by following the "best practice" of always have a '.' in your ng-models

so

<input ng-model="tweetText">

becomes

<input ng-model="tweet.text">

A great summary is here:

https://www.youtube.com/watch?v=ZhfUv0spHCY&feature=youtu.be&t=30m

Neil Ellis
  • 111
  • 1
  • 4