This has bitten me twice in the last 3 days so I'm doing a quick post to remind myself.

With AngularJS models, you typically have two way bindings between UI elements and your controller's properties. Directly from the docs (Plunker)

<!doctype html>
<html ng-app>
 <script src=""></script>
 <script src="script.js"></script>


<form name="myForm" ng-controller="Ctrl">
 Single word: <input type="text" name="input" ng-model="text"
 ng-pattern="word" required>
 <span class="error" ng-show="myForm.input.$error.required">
 <span class="error" ng-show="myForm.input.$error.pattern">
 Single word only!</span>

<tt>text = </tt><br/>
 <tt>myForm.input.$valid = </tt><br/>
 <tt>myForm.input.$error = </tt><br/>
 <tt>myForm.$valid = </tt><br/>
 <tt>myForm.$error.required = </tt><br/>

<!-- more -->JavaScript

function Ctrl($scope) {
 $scope.text = 'guest';
 $scope.word = /^\w*$/;

This all works great until you get a simple property that's a 'primitive' so numbers, boolean etc. and you need to use this property within an angular repeater or another directive which creates its own scope. The problem is that, because JavaScript is a pass by value language, primitive types are copied within nested scopes. This means that, if a property changes within a local scope, the original/parent version of the property isn't updated with those changes. Not only that, angular (for good reason) no longer allow duplicates within a repeater, which is what lead me to StackOverflow the first time I encountered this.

The solution is simply replace the primitive with a JavaScript hash/object so instead of doing something like this:

function Ctrl($scope) {
$scope.myProperty =true;

You should do

function Ctrl($scope) {
$scope.myProperty ={someName:true};

I highly recommend watching this talk by Miško Hevery on AngularJS best practices. I've watched it...not I just need to remember all of it :D


For further reading, Jim Hoskins did a more in depth write up on nested scopes in AngularJS.