Угловая разбивка на страницы не обновляется при изменении связанного списка из-за фильтрации в текстовом поле ввода

Вот сценарий:

Я использую сайт ASP.NET MVC с Angular JS и пользовательским интерфейсом Boostrap. У меня есть динамический список ul, заполненный данными, поступающими через вызов контроллера в AngularJS, фильтрующий этот список через окно поиска ввода. Список также управляется с помощью нумерации страниц (управление начальной загрузкой пользовательского интерфейса), которую я настроил для отображения 10 результатов на странице для списка примерно из 100 элементов. Этот список фильтруется по мере того, как пользователь вводит в поле поиска, однако я бы хотел, чтобы нумерация страниц также обновлялась, поэтому рассмотрим следующий пример:

Список содержит 10 страниц элементов (100 элементов), пользователь вводит некоторый текст в поле поиска ввода, которое фильтрует список до 20 или около того элементов, поэтому нумерация страниц должна быть обновлена ​​с 10 страниц до двух страниц.

Я полагаю, что где-то должна быть настройка $watch, возможно, в элементах списка после того, как она была отфильтрована, а затем обновить количество страниц разбивки на страницы, однако я новичок в AngularJS, поэтому может кто-нибудь объяснить мне, как это можно сделать?

Большое спасибо. Я разместил свой код ниже:

<div data-ng-app="dealsPage">
<input type="text" data-ng-model="cityName" />
<div data-ng-controller="DestinationController">
    <ul>
        <li data-ng-repeat="deals in destinations | filter: cityName |
            startFrom:currentPage*pageSize | limitTo:pageSize">{{deals.Location}}</li>
    </ul>
    <br />
    <pagination rotate="true" num-pages="noOfPages" current-page="currentPage" 
                max-size="maxSize" class="pagination-small" boundary-links="true"></pagination>
</div>

 var destApp = angular.module('dealsPage', ['ui.bootstrap', 'uiSlider']);
destApp.controller('DestinationController', function ($scope, $http) {
    $scope.destinations = {};
    $scope.currentPage = 1;
    $scope.pageSize = 10;

    $http.get('/Deals/GetDeals').success(function (data) {
        $scope.destinations = data;
        $scope.noOfPages = data.length / 10;
        $scope.maxSize = 5;
    });
});

destApp.filter('startFrom', function () {
    return function (input, start) {
        start = +start; //parse to int
        return input.slice(start);
    };
});



Ответы (3)


Поскольку ваша разбивка на страницы представляет собой комбинацию связанных фильтров, Angular понятия не имеет, что при изменении cityName он должен сбрасывать currentPage на 1. Вам нужно будет справиться с этим самостоятельно с помощью собственного $watch.

Вы также можете настроить фильтр startFrom так, чтобы он произносил (currentPage - 1) * pageSize, иначе вы всегда будете начинать со страницы 2.

Как только вы это сделаете, вы заметите, что ваша нумерация страниц не точна, потому что она по-прежнему основана на destination.length, а не на отфильтрованном подмножестве пунктов назначения. Для этого вам нужно будет перенести логику фильтрации из вашего представления в ваш контроллер следующим образом:

http://jsfiddle.net/jNYfd/

HTML

<div data-ng-app="dealsPage">
    <input type="text" data-ng-model="cityName" />
    <div data-ng-controller="DestinationController">
        <ul>
            <li data-ng-repeat="deals in filteredDestinations | startFrom:(currentPage - 1)*pageSize | limitTo:pageSize">{{deals.Location}}</li>
        </ul>
        <br />
        <pagination rotate="true" num-pages="noOfPages" current-page="currentPage" max-size="maxSize" class="pagination-small" boundary-links="true"></pagination>
    </div>

JavaScript

var destApp = angular.module('dealsPage', ['ui.bootstrap']);

destApp.controller('DestinationController', function ($scope, $http, $filter) {
    $scope.destinations = [];
    $scope.filteredDestinations = [];

    for (var i = 0; i < 1000; i += 1) {
        $scope.destinations.push({
            Location: 'city ' + (i + 1)
        });
    }

    $scope.pageSize = 10;
    $scope.maxSize = 5;

    $scope.$watch('cityName', function (newCityName) {
        $scope.currentPage = 1;
        $scope.filteredDestinations = $filter('filter')($scope.destinations, $scope.cityName);
        $scope.noOfPages = $scope.filteredDestinations.length / 10;
    });
});

destApp.filter('startFrom', function () {
    return function (input, start) {
        start = +start; //parse to int
        return input.slice(start);
    };
});
person Langdon    schedule 08.09.2013
comment
Большое спасибо! Это сработало хорошо. :) Все, что мне нужно было сделать, это добавить эту строку кода в ваше решение: $scope.noOfPages = isNaN($scope.filteredDestinations.length / 10) ? 200 : $scope.filteredDestinations.length / 10; Чтобы при запуске страницы элемент управления разбивкой на страницы пользовательского интерфейса boostrap отображался, иначе он не отображался из-за того, что переменная $scope.noOfPages имеет ' Значение NaN. - person Ben; 09.09.2013
comment
Круто, рад, что помог. Добро пожаловать в StackOverflow, кстати. Вам следует подумать о том, чтобы принять ответ, если он ответил на ваш вопрос. :) - person Langdon; 09.09.2013
comment
Кроме того, не могли бы вы помочь мне с аналогичной проблемой, поскольку я застрял на этом сейчас. Я разместил его на другой странице, вот ссылка: stackoverflow.com/questions/18722246/ Еще раз большое спасибо. - person Ben; 10.09.2013

Версия, размещенная на jsfiddle, совместима с ui-bootstrap 0.5.0, но начиная с 0.6.0 в нее вносились критические изменения.

Вот версия, которая использует следующие библиотеки:

  • угловой 1.2.11
  • угловой интерфейс начальной загрузки 0.10.0
  • бутстрап 3.1.0

Вот плункер для того же самого:

Разбиение на страницы начальной загрузки Angular UI

person Amarjeet Singh    schedule 04.02.2014
comment
Ваш плункер полагается на получение js из github, запрос на который отклонен. Лучший вариант - cdnjs. plnkr.co/edit/1TfUI2DFejQ2ULamfwu9?p=preview - person mg1075; 26.06.2014
comment
Кроме того, я считаю, что API для разбиения на страницы начальной загрузки теперь имеет атрибут ng-model, а не атрибут page, который использует plunkr. angular-ui.github.io/bootstrap/#/pagination - person mg1075; 26.06.2014

Привет, я пытался подключить это к Firebase с помощью Angular Fire, и это работает только после того, как я наберу что-то в поисковом вводе. В методе $scope.$watch я использовал orderByPriorityFilter Angular Fire для преобразования объекта в массив.

$scope.$watch('search', function(oldTerm, newTerm) {
  $scope.page = 1;
  // Use orderByPriorityFilter to convert Firebase Object into Array
  $scope.filtered = filterFilter(orderByPriorityFilter($scope.contacts), $scope.search);
  $scope.lastSearch.search = oldTerm;
  $scope.contactsCount = $scope.filtered.length;
});

Первоначальная загрузка не загружает никаких контактов. Это только после того, как я начну печатать в поле поиска ввода.

person thienedits    schedule 30.03.2014