Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the angularjs way to databind many inputs?

I'm learning angularjs and I want to be able let the user enter many inputs. When these inputs are entered the list array elements should change accordingly. I wanted to try using ngRepeat directive but I read that since it creates a new scope I cannot databind:

<div ng-repeat="item in list">     <label>Input {{$index+1}}:</label>     <input ng-model="item" type="text"/> </div> 

I was wondering if I should be using a custom directive to do this or approach it differently.

like image 974
rcell Avatar asked Oct 19 '12 15:10

rcell


People also ask

What is 2 way data binding in AngularJS?

Two-way Binding Data binding in AngularJS is the synchronization between the model and the view. When data in the model changes, the view reflects the change, and when data in the view changes, the model is updated as well.

What is AngularJS one-way data binding?

The one-way data binding is an approach where a value is taken from the data model and inserted into an HTML element. There is no way to update model from view. It is used in classical template systems. These systems bind data in only one direction.

What is the use of rootScope in AngularJS?

All applications have a $rootScope which is the scope created on the HTML element that contains the ng-app directive. The rootScope is available in the entire application. If a variable has the same name in both the current scope and in the rootScope, the application uses the one in the current scope.

How does AngularJS binding work?

AngularJS handle data-binding mechanism with the help of three powerful functions : $watch(),$digest()and $apply(). Most of the time AngularJS will call the $scope. $watch() and $scope. $digest(), but in some cases you may have to call these functions manually to update with new values.


1 Answers

The reason that databinding to a primitive "item" doesn't work is because of the way ng-repeat creates the child scopes for each item. For each item, ng-repeat has the new child scope prototypically inherit from the parent scope (see dashed lines in picture below), and then it assigns the item's value to a new property on the child scope (red items in picture below). The name of the new property is the loop variable's name. From the ng-repeat source code:

childScope = scope.$new(); ... childScope[valueIdent] = value; 

If item is a primitive, the new child scope property is essentially assigned a copy of the primitive's value. This child scope property is not visible to the parent scope, and changes you make to the input field are stored in this child scope property. E.g., suppose we have in the parent scope

$scope.list = [ 'value 1', 'value 2', 'value 3' ]; 

And in the HTML:

<div ng-repeat="item in list"> 

Then, the first child scope would have the following item property, with a primitive value (value 1):

item: "value 1" 

ng-repeat with primitives

Because of the ng-model databinding, changes you make to the form's input field are stored in that child scope property.

You can verify this by logging the child scope to the console. Add to your HTML, inside the ng-repeat:

<a ng-click="showScope($event)">show scope</a> 

Add to your controller:

$scope.showScope = function(e) {     console.log(angular.element(e.srcElement).scope()); } 


With @Gloopy's approach, each child scope still gets a new "item" property, but because list is now an array of objects, childScope[valueIdent] = value; results in the item property's value being set to a reference to one of the array objects (not a copy).

ng-repeat with objects

Using the showScope() technique, you'll see that the child scope item property's value references one of the array objects -- it is no longer a primitive value.

See also don't bind to primitives in ng-repeat child scopes and
What are the nuances of scope prototypal / prototypical inheritance in AngularJS? (which contains pictures of what the scopes look like when using ng-repeat).

like image 147
Mark Rajcok Avatar answered Oct 13 '22 00:10

Mark Rajcok