ng-repeat and ng-controller on the same DOM element
Solution 1
You should break your controller into UserListController
and UserController
. The list of users should be part of UserListController and the each item can be managed by UserController
Something like
<table ng-controller='UserListController'>
<tbody ng-controller="UserController" ng-repeat="user in users" ng-click="toggleSelectedUser()" ng-switch on="isSelectedUser()" ng-init="user=user">
So the user controller becomes
angular.module("myApp", [])
.controller("UserController", ["$scope", function($scope) {
$scope.selected = false;
$scope.toggleSelectedUser = function() {
$scope.user.selected = !$scope.selected;
};
$scope.isSelectedUser = function() {
return $scope.user.selected;
};
}]);
Solution 2
What I want is the variable selected should be unique for each scope.
Yes you can.
Multiple controller way
You can create root controller mainController
and add to your model users
new controller per user.
After that, call new controller in ng-repeat as ng-controller="user.ctrl"
Demo Fiddle
I would write something like:
HTML
<div ng-controller="mainController">
<table>
<tbody ng-repeat="user in users" ng-controller="user.ctrl" ng-click="toggleSelectedUser()" ng-switch on="isSelectedUser()">
<tr>
<td>{{user.name}}</td>
<td>{{user.email}}</td>
</tr>
<tr ng-switch-when="true">
<td colspan="2" style="padding-left: 10px">{{user.desc}}</td>
</tr>
</tbody>
</table>
</div>
JS
var fessmodule = angular.module('myModule', []);
fessmodule.controller('mainController', function ($scope) {
$scope.users = [{
ctrl: fooCtrlA,
name: "AAAAA",
email: "[email protected]",
desc: "Description about AAAA"
}, {
ctrl: fooCtrlB,
name: "BBBBB",
email: "[email protected]",
desc: "Description about BBBBB"
}, {
ctrl: fooCtrlC,
name: "CCCCC",
email: "[email protected]",
desc: "Description about CCCC"
}];
});
fessmodule.$inject = ['$scope'];
function fooCtrlA($scope) {
$scope.selected = true;
$scope.toggleSelectedUser = function () {
$scope.selected = !$scope.selected;
};
$scope.isSelectedUser = function () {
return $scope.selected;
};
}
function fooCtrlB($scope) {
$scope.selected = false;
$scope.toggleSelectedUser = function () {
$scope.selected = !$scope.selected;
};
$scope.isSelectedUser = function () {
return $scope.selected;
};
}
function fooCtrlC($scope) {
$scope.selected = false;
$scope.toggleSelectedUser = function () {
$scope.selected = !$scope.selected;
};
$scope.isSelectedUser = function () {
return $scope.selected;
};
}
However you can see we have code duplicate!!. Each "child" controller has the same logic:
$scope.selected = false;
$scope.toggleSelectedUser = function () {
$scope.selected = !$scope.selected;
};
$scope.isSelectedUser = function () {
return $scope.selected;
};
If you want to make your code work, I would use ng-model
.
Other way with ng-model
Demo 2 Fiddle
HTML
<tbody ng-repeat="user in users" ng-click="toggleSelectedUser(user)" ng-switch on="isSelectedUser(user)">
<tr ng-model="user">
<td>{{user.name}}</td>
<td>{{user.email}}</td>
</tr>
<tr ng-switch-when="true">
<td colspan="2" style="padding-left: 10px">{{user.desc}}</td>
</tr>
</tbody>
and controller with modified model:
var fessmodule = angular.module('myModule', []);
fessmodule.controller('mainController', function ($scope) {
$scope.users = [{
selected: false,
name: "AAAAA",
email: "[email protected]",
desc: "Description about AAAA"
}, {
selected: false,
name: "BBBBB",
email: "[email protected]",
desc: "Description about BBBBB"
}, {
selected: false,
name: "CCCCC",
email: "[email protected]",
desc: "Description about CCCC"
}];
$scope.toggleSelectedUser = function (user) {
user.selected = !user.selected;
};
$scope.isSelectedUser = function (user) {
return user.selected;
};
});
Anup Vasudeva
I am passionate about .NET technologies, have pretty much exposure on C#, ASP.NET Web forms and MVC, WCF, WPF, Silverlight, JavaScript and jQuery.
Updated on July 24, 2022Comments
-
Anup Vasudeva almost 2 years
Can we attach ng-controller and ng-repeat to the same DOM element? Fiddle
Here is the HTML:
<table> <tbody ng-controller="UserController" ng-repeat="user in users" ng-click="toggleSelectedUser()" ng-switch on="isSelectedUser()"> <tr> <td>{{user.name}}</td> <td>{{user.email}}</td> </tr> <tr ng-switch-when="true"> <td colspan="2"> {{user.desc}} </td> </tr> </tbody> </table>
Here is the code:
angular.module("myApp", []) .controller("UserController", ["$scope", function($scope) { $scope.users = [ {name : "Anup Vasudeva", email : "[email protected]", desc : "Description about Anup Vasudeva"}, {name : "Amit Vasudeva", email : "[email protected]", desc : "Description about Amit Vasudeva"}, {name : "Vijay Kumar", email : "[email protected]", desc : "Description about Vijay Kumar"} ]; $scope.selected = false; $scope.toggleSelectedUser = function() { $scope.selected = !$scope.selected; }; $scope.isSelectedUser = function() { return $scope.selected; }; }]);
I think it makes sense to bind
ng-controller
andng-repeat
to the same DOM element. The scope created by ng-repeat can be managed by the controller. What I want is the variableselected
should be unique for each scope. -
Anup Vasudeva over 10 yearsThanks for the reply. In your first solution, do you think there would be an issue if my number of users scales? In your second solution, the ng-controller and ng-repeat are in the different DOM element. Would it be possible to have both ng-controller and ng-repeat in the same DOM element?
-
Maxim Shoustin over 10 yearsAs you see if we talk about functionality 2nd way work as well. About 1st solution, you can't put main controller to
ng-repeat
. Becauseng-repeat
DOM element represents item akauser
, notusers
. We need someone who will manage allusers
model. So as I know - no way. -
Homer almost 10 yearsHow would this look using the "controller as" syntax?
-
Matthias over 9 yearsCan you explain the purpose of
ng-init="user=user"
? It seems redundant, but if the ngRepeat changed tong-repeat="singleUser in users"
then you could change it tong-init="user=singleUser"
without changing the controller code. Is that the only reason?