patternjavascriptMinor
Controller structure for a browser game module with filters and pagination
Viewed 0 times
paginationwithmodulebrowsercontrollergameforstructurefiltersand
Problem
To get an idea of what the controller code reflects, here is a screenshot:
Basically, the idea is that you print out a list of football players which you can then filter by their name, price, field position, and team. I'm not sure whether it's better to handle all the scope logic within a single controller, or break it down into separate controllers, isolating the filters from the player list, pagination, and so on. I'm currently going with the single controller approach, and here's what I have:
```
app.controller('playersController', function($scope, $filter, minMax, buildOptions, PlayersModel, TeamsModel, CommonValues){
$scope.basehref = CommonValues.getBaseHref();
$scope.imgbase = CommonValues.getImgBase();
$scope.players = PlayersModel;
$scope.teams = TeamsModel;
$scope.predicate = 'team.name';
$scope.minMax = minMax($scope.players);
$scope.filters = { // filter model
searchString: '', // string input from user
selectedTeam: {}, // selected team
selectedTeamMs: [], // selected teams from multiselect
roles: {
1: true, // forward
2: true, // defense
3: true, // midfield
4: true // goalie
},
slider: { // set up boundaries for slider filter
min: $scope.minMax[0],
max: $scope.minMax[1],
step: 10000
},
pagination: { // set up pagination
totalItems: $scope.players.length,
currentPage: 1,
maxSize: 5,
pages: buildPages()
}
};
var cache = $scope.players; // save original player model for later use
/
* Watchers
/
// watch for filter model changes, start filtering
$scope.$watch('filters', function(newVal, oldVal){
if (newVal !== oldVa
Basically, the idea is that you print out a list of football players which you can then filter by their name, price, field position, and team. I'm not sure whether it's better to handle all the scope logic within a single controller, or break it down into separate controllers, isolating the filters from the player list, pagination, and so on. I'm currently going with the single controller approach, and here's what I have:
```
app.controller('playersController', function($scope, $filter, minMax, buildOptions, PlayersModel, TeamsModel, CommonValues){
$scope.basehref = CommonValues.getBaseHref();
$scope.imgbase = CommonValues.getImgBase();
$scope.players = PlayersModel;
$scope.teams = TeamsModel;
$scope.predicate = 'team.name';
$scope.minMax = minMax($scope.players);
$scope.filters = { // filter model
searchString: '', // string input from user
selectedTeam: {}, // selected team
selectedTeamMs: [], // selected teams from multiselect
roles: {
1: true, // forward
2: true, // defense
3: true, // midfield
4: true // goalie
},
slider: { // set up boundaries for slider filter
min: $scope.minMax[0],
max: $scope.minMax[1],
step: 10000
},
pagination: { // set up pagination
totalItems: $scope.players.length,
currentPage: 1,
maxSize: 5,
pages: buildPages()
}
};
var cache = $scope.players; // save original player model for later use
/
* Watchers
/
// watch for filter model changes, start filtering
$scope.$watch('filters', function(newVal, oldVal){
if (newVal !== oldVa
Solution
First of all, for a better user experience, I would avoid pagination in favour of infinite scroll. Here is a simple Angular infinite scroll implementation
I presume you are aware of minification-proof technique
Next, I see many fields like
The hard-coded declation
Also I presume you are aware of the difference between using
EDIT.
Unless you know what you are doing, a recommended practice is to use
EDIT.
See also Misko's video on best practices, including putting the dot inside your
I am not sure why you define filters inside a controller, rather than with
Usually filters declared via
I presume you are aware of minification-proof technique
.controller('name', ['$scope', function($scope){}], so won't go into that.Next, I see many fields like
$scope.players, $scope.teams, ..., mixed with $scope.filters, which can lead to namespace conflicts as the app grows. Hence I would gather all data-related fields into one object like $scope.data. Then you can simply pass the whole object from your service instead of assigning one-by-one.The hard-coded declation
$scope.predicate = 'team.name'; is mixed with others provided by the service. Perhaps it belongs to a Config service together with other hard-coded properties.Also I presume you are aware of the difference between using
$scope.field vs $scope.field.subfield in terms of their interactions with parent and child scopes.EDIT.
Unless you know what you are doing, a recommended practice is to use
$scope.field.subfield. That way, in a child controller, you have both read and write access to it. If instead you use $scope.field, then changing it from a child controller will add a variable on the local scope but won't change the parent scope as you likely intend, see here.EDIT.
See also Misko's video on best practices, including putting the dot inside your
$scope property.minMax($scope.players); suggests that you are using service minMax just for one function. I would gather those functions into one bigger service like Utils. You already have lots of dependencies for your controller, so lowering that number can be a good thing. Similar for $scope.teams = TeamsModel;.I am not sure why you define filters inside a controller, rather than with
.filter as common. Usually filters declared via
.filter update themselves, so no need for watchers.Context
StackExchange Code Review Q#47499, answer score: 2
Revisions (0)
No revisions yet.