akronymn
akronymn

Reputation: 2446

How to create unique ng-form tags on a form with ng-repeat in angular

I am trying to create a form part of which is a table that loops over a list of objects and for each object allows the user to check/uncheck attributes. The rest of the form works fine but I am having trouble setting the ng-model attribute on the checkboxes.

Here's what I have:

<table>
    <thead>
        <tr>
            <td>Objects and Fields</td>
            <td>Createable</td>
            <td>Deleteable</td>
            <td>Readable</td>
            <td>Updateable</td>
        </tr>
      </thead>
      <tbody>
        <tr ng-repeat="object in myAppObjects">
          <td>
            {{object.name}}&nbsp;{{object.id}}
            <input type="checkbox" name="app_access_{{object.id}}" ng-model="app_access" value="false">
          </td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
        </tr>
      </tbody>
</table>

At first I tried setting the ng-model="app_access_{{object.id}}" so that I would have a unique ng-model for each cell. This caused the table row to be repeated several dozen times. Each of those empty cells will also have a check box. There will be five check boxes for each object and several objects in the form at a given time. I'll need to be able to access each check box (or better yet a list of the checked ones) in the controller.

Upvotes: 2

Views: 3730

Answers (2)

Mark Rajcok
Mark Rajcok

Reputation: 364687

Since ngRepeat creates a new (child) scope for each item, creating new ng-models (that are tied to those new scopes) for the items will not work because those models/data will only be accessible inside those inner scopes. We can't write a controller function to access those inner/child scopes. It is better to reference something in myAppObjects for the models (like @Max suggests in his second example).

If myAppObjects looks something like this:

$scope.myAppObjects = [
  {id: 1, cb1: true,  cb2: false, cb3: true, cb4: true,  cb5: false },
  {id: 2, cb1: false, cb2: false, cb3: true, cb4: false, cb5: true  },

You could write your ng-repeat like this:

<tr ng-repeat="appObj in myAppObjects">
    <td>{{appObj.id}}
        <input type="checkbox" ng-model="appObj.cb1"></td>
    <td><input type="checkbox" ng-model="appObj.cb2"></td>
    <td><input type="checkbox" ng-model="appObj.cb3"></td>
    <td><input type="checkbox" ng-model="appObj.cb4"></td>
    <td><input type="checkbox" ng-model="appObj.cb5"></td>
</tr>

Working fiddle: http://jsfiddle.net/mrajcok/AvGKj/

Bottom line: we need to have the checkbox models defined in/on the parent scope (in my fiddle, MyCtrl's $scope), and not in/on the ngRepeat inner/child scopes.

Upvotes: 3

Max
Max

Reputation: 8836

Generally, if you are iterating over a collection using ng-repeat then the the items that you display and edit are the individual members of the collection. So if you have an array of strings that are being edited by the ng-repeat you would do

<div ng-repeat="item in list">
  <input ng-model="item" />
</div>

Or if is a list of objects you are iterating over you would do

<div ng-repeat="obj in list">
  <input ng-model="obj.item" />
</div>

Upvotes: 0

Related Questions