Динамическая маршрутизация с элементом массива в angularjs после фильтрации массива
У меня проблема с моим приложением angularjs, когда мое приложение перенаправляет на неправильную страницу при использовании массива ng-repeat для определения маршрута.
данные выглядят так и доступны в контроллере person:
[
{
"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: (тег привязки ссылается на человека на основе его индекса в массиве (я думаю, что это может быть то, что мне нужно изменить, чтобы исправить проблему, но я не уверен)
<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>
Маршрутизация от angular: (маршрут с '/person/:itemId' является маршрутизацией на страницу, специфичную для конкретного пользователя, где их индекс в массиве определяет их идентификатор)
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');
});
Вот контроллер для динамической страницы. Он отлично работает для исходного массива, но как только я пытаюсь отсортировать массив, индекс больше не соответствует правильному ученику.
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];
});
Таким образом, функциональная проблема заключается в том, что индекс применяется к первому ученику в большом массиве данных. Кажется, он работает отлично, и правильные данные заполняют страницу, но когда я использую ввод html / text для фильтрации списка, исходные индексы обновляются на стороне html и не соответствуют исходному массиву. Таким образом, маршрутизация отправляет их не на ту страницу.
Как сделать так, чтобы маршрутизация работала даже для отфильтрованного списка?
2 ответа
Один из способов сделать это - использовать функцию, которая возвращает вам индекс, который был у студента в исходном массиве для каждого студента в вашем ng-repeat
,
$scope.getIndex = function(student) {
return $scope.students.indexOf(student);
}
Затем вы можете вызвать функцию в вашем списке, как:
<a ng-href="/#person/{{getIndex(student)}}">
Это, однако, не самый производительный код, который вы можете себе представить.
Другой способ - просто временно сохранить индекс ученика как свойство и использовать его для ссылки на него, опять же, не самое удачное решение:
$scope.students = $scope.students.map(function(student, index) {
student.index = index;
return student;
});
И в списке:
<a ng-href="/#person/{{student.index}}">
Однако, если вы можете как-то назначить студентам уникальный идентификатор, это определенно будет предпочтительным способом. Таким образом, вы также убедитесь, что вы всегда ссылаетесь на одного и того же студента. Если твой students.json
как-то меняется между временем создания списка и временем, когда пользователь нажимает на элемент, вы можете снова ссылаться на неправильный...
Кстати всегда пользуюсь ng-href
при включении заполнителей в ссылку. Почему вы должны это сделать, хорошо описано в документации по Angular API:
Использование разметки Angular наподобие {{hash}} в атрибуте href заставит ссылку перейти на неверный URL, если пользователь щелкнет по ней до того, как Angular сможет заменить разметку {{hash}} ее значением. Пока Angular не заменит разметку, ссылка будет разорвана и, скорее всего, вернет ошибку 404. Директива ngHref решает эту проблему.
Вы создаете ng-repeat, используя некоторый объект в $ scope, называемый студентов, правильно? Если он создается из того же самого student.json, что и в вашем контроллере, то их идентификаторы учеников должны быть логически эквивалентны. Так что просто поменяйте href с "/#person/{{$index}}" на "/#person/ndom averagestudent.studentId}}".
Если по какой-то причине они не совпадают, то при создании объекта учеников вы можете добавить новый атрибут studentId, который содержит значение их индекса в массиве, а затем использовать предыдущее предложение.
Просто помните, что при использовании ng-repeat, если у вас есть идентичные объекты, он выдаст ошибку, поэтому вы должны добавить к нему "track by $index".