Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS: ng-model setter inside ng-repeat

I've found some great answers on how to get the value of an ng-model inside an ng-repeat, but so far, I haven't found any that cover the setter. Suppose I have something like this:

<div ng-repeat="item in getItems()">
    <input ng-model="itemTitle" ng-model-options={getterSetter:true}">
</div>

If I had a single input box, I'd use something like this:

...
var _val = '';
$scope.itemTitle = function(val){
    return angular.isDefined(val) ? (_val = val) : _val;
}
...

However, that would change the value for every single input box. Is it possible to define the variables and a setter, potentially using arrays? Or is there a better method to get and set input boxes inside an ng-repeat?

like image 263
CJ Harries Avatar asked Jan 18 '15 00:01

CJ Harries


People also ask

Why we use[( ngModel)]?

The ngModel directive is a directive that is used to bind the values of the HTML controls (input, select, and textarea) or any custom form controls, 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 form validations.

What is difference between ng-repeat and Ng options?

ng-repeat creates a new scope for each iteration so will not perform as well as ng-options. For small lists, it will not matter, but larger lists should use ng-options. Apart from that, It provides lot of flexibility in specifying iterator and offers performance benefits over ng-repeat.

Does ng-repeat create a new scope?

The controller creates a child scope and the ng-repeat , which will create an LI element for each item in the list of To Do items. It also creates a new scope for each element.

What is ng-repeat in AngularJS?

AngularJS ng-repeat Directive The ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object. Note: Each instance of the repetition is given its own scope, which consist of the current item.


2 Answers

The answer by Wayne Ellery does answer the question as it shows "a better method to get and set input boxes inside an ng-repeat".

However if you actually want to use ng-model-options="{getterSetter: true}" within an ng-repeat as is implied in the question and the comments then it's a little more complicated as within your getterSetter function you don't know which item from the ng-repeat is being referred to.

Essentially what you need to do is pass a different getter/setter function for each item, and you can do that by passing a function to ng-model that creates your row specific getter/setter for you.

<div ng-app="app" ng-controller="ctrl">
  <div ng-repeat='row in items'>
    <span>{{row.name}}</span>
    <input type='text' ng-model='createTitleGetterSetter(row.name)' 
      ng-model-options='{ getterSetter: true }' />
  </div>
  <hr/>
  <pre>{{ itemTitles | json }}</pre>
</div>

And the JS code:

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

app.controller('ctrl', function($scope) {
    $scope.items = [
        {'name': 'a'},
        {'name': 'b'},
        {'name': 'c'}
    ];

    $scope.itemTitles = {};
    $scope.createTitleGetterSetter = function(name) {
        if (!$scope.itemTitles[name]) {
            $scope.itemTitles[name] = {
                getterSetter: function(newValue) {
                        return arguments.length === 0 ? 
                        $scope.itemTitles[name].title :
                        $scope.itemTitles[name].title = newValue;
                },
                title: ''
            }
        }

        return $scope.itemTitles[name].getterSetter;
    };
});

JSFiddle here: http://jsfiddle.net/zLg3mLd0/1/

In this case the item titles are of course not stored along with the item objects (if you wanted to do that, just a simple ng-model would suffice) but in the itemTitles map.

Credit to this answer and its comments on which this answer is heavily based.

like image 161
mluisbrown Avatar answered Sep 27 '22 20:09

mluisbrown


You would set ng-model to item.title so each object in the array returned from getItems() would contain a title.

<div ng-repeat="item in getItems()">
    <input type="text" ng-model="item.title"/>
</div>
like image 24
Wayne Ellery Avatar answered Sep 27 '22 21:09

Wayne Ellery