I have a problem with my angularjs app where my app is routing to the wrong page when using an ng-repeat array to determine the route.
data looks like this and is accessed in the person controller:
[
{
"name":"AJ lastname",
"img_name":"AJ_lastname",
"location":"Baltimore, Maryland",
"info":"stuff"
},
{
"name":"Albert lastname",
"img_name":"Albert_lastname",
"location":"Boston, Massachusetts",
"info":"stuff"
} // ... more data
]
html: (the anchor tag links to the person based on their index in the array (I believe this may be what I need to change to fix the problem, but I'm not sure)
<ul class="main-list">
<li class="list-item fade" ng-repeat="student in students | filter:filter">
<a href="/#person/{{$index}}">
<img class="portrait listimg" ng-src="/images/{{student.img_name}}.jpg" alt="portrait of {{student.name}}">
<h2>{{student.name}}</h2>
<h4>{{student.location}}</h4>
</a>
</li>
</ul>
Routing from angular: (the route with '/person/:itemId' is routing to a page specific to a specific user, where their index in the array determines their id)
app.config(function ($routeProvider, $httpProvider) {
$routeProvider
.when('/list', {
templateUrl: './js/templates/list.html',
controller: 'ListController'
})
.when('/person/:itemId', {
templateUrl: './js/templates/person.html',
controller: 'PersonController'
})
.otherwise('/list');
});
Here is the controller for the dynamic page. It works perfectly for the original array, but once I attempt to sort the array, the index no longer corresponds to the correct student.
app.controller('PersonController', function ($scope, $http, $routeParams) {
$scope.person = 'Someone\'s name';
$http.get('../js/students.json').success(function (data) {
$scope.allStudents = data;
$scope.studentId = $routeParams.itemId;
$scope.student = data[$scope.studentId];
});
So the functional problem is that the index applies to the first student in the large array of data. It appears to work perfectly, and the correct data populates the page, but when I use the html/text input to filter the list, the original indices are updated on the html side, and they do not correspond to the original array. So the routing sends them to the wrong page.
How can I make the routing work even for a filtered list?
One way you can do this is by using a function which returns you the index a student had in the original array for each student in your
ng-repeat
.You can then call the function in your list like:
This though is not quite the most performant code you could imagine.
Another way would be to just temporarily store the index of the student as a property and use that one to reference it, again not quite the nicest solution:
And in the list:
However, if you can somehow assign the students a unique id that would definitely be the preferred way. That way you also make sure that you always reference the same student. If your
students.json
somehow changes between the time you create the list and the time the user clicks on an item you may reference the wrong one again...By the way always use
ng-href
when including placeholders in the link. Why you should do so is well described in the Angular API docs:You are creating the ng-repeat using some object on $scope called students, correct? If this is being built from the same students.json as in your controller then their student ids should logically be equivalent. So just change the href from "/#person/{{$index}}" to "/#person/{{student.studentId}}".
If for some reason they aren't the same then when you create the students object you can add a new attribute, studentId, which holds the value of their index in the array and then use the previous suggestion.
Just remember that when using ng-repeat if you have identical objects it'll throw an error so you have to add the "track by $index" to it.