AngularJS - 将对象转换为数组以进行UI Bootstrap分页

时间:2015-07-31 18:28:02

标签: angularjs restangular

我知道这可能已经得到了回答,但是我没有成功应用我在我的例子中找到的任何解决方案。我正在尝试使用UI Bootstrap在我的产品列表页面上启用分页,并允许用户通过搜索过滤所述结果。

我有一个定义如下的对象:

$scope.products = [{"_id": ObjectID("0000000"), "name":"Product", "description": "Product Description"}];

到目前为止,我已经能够从restangular服务中提取产品,但是当我添加分页/搜索功能时,我收到以下控制台错误:Error: [filter:notarray] Expected array but received {}。我知道我需要将我的对象转换为数组,但我无法成功转换它。我试过的两个例子发布在下面。任何帮助将不胜感激。

我的产品列表视图

<div ng-controller="paginationCtrl" class="row">
    <div class="col-lg-12">
        <div class="pull-left">
            <form>
                <div class="input-group product-searchs" ng-controller="SearchCtrl">
                    <label class="sr-only" for="searchProducts">Search</label>
                    <span class="input-group-addon search-icon"><i class="fa fa-search" aria-hidden="true"></i></span>
                    <input type="text" class="form-control" id="searchProducts" ng-model="search.name" placeholder="Search for products">
                    <span class="input-group-addon clear-icon">
                        <button type="button" ng-click="clearSearch()">
                            <i class="glyphicon glyphicon-remove" aria-hidden="true"></i>
                        </button>
                    </span>
                </div>
            </form>
        </div>
    </div>
    <div class="col-lg-12">
        <div class="list-group">
            <a ui-sref="productDetails({id:product._id})"  class="list-group-item clearfix" ng-repeat="product in filteredProducts = (products | filter: search | startFrom: (currentPage - 1) * itemsPerPage | limitTo: itemsPerPage | orderBy:orderProp)">
                <div class="page-header clearfix">
                    <h2 class="pull-left"><i class="fa fa-diamond"></i> {{product.name}}</h2>
                    <span class="pull-right product-price {{product.price | currency}}</span>
                </div>
                {{product.description}}
            </a>
        </div>
    </div>
    <div class="col-lg-12">
        <pagination class="pull-right" page="currentPage" total-items="totalItems" ng-model="currentPage" max-size="maxSize" ng-change="pageChanged() items-per-page="itemsPerPage" num-pages="numPages"></pagination>
    </div>
</div>

我知道我可能会有一些额外的依赖注入,一旦我使其正常工作,我将删除它。

我的控制器

angular.module('gemStoreApp')
   .controller('paginationCtrl', ['$scope', '$log', 'filterFilter', 'productsService', 'Restangular', '$filter', function ($scope, $log, filterFilter', productsService, Restangular, $filter) {

   $scope.search = {}

   $scope.filteredProducts = [];

   //Option 1
   angular.forEach($scope.products, function(product) {
       $scope.filteredProducts.push(product);
   });

   //Option 2
   //for (var key in $scope.products) {
       //var tempProducts = {};
       //tempProducts[key] = $scope.products[key];
       //$scope.filteredProducts.push(tempProducts);
   //});

   $scope.currentPage = 1;
   $scope.maxSize = 100;
   $scope.itemsPerPage = 10;

   $scope.$watch('search', function(newVal, oldVal) {
       $scope.filteredProducts = filterFilter($scope.products, newVal);
       $scope.totalItems = $scope.filteredProducts.length;
   }, true);

   //I also tried this
   //$scope.$watch('search, function(newSearch) {
       //$scope.filteredProducts = $filter('filter')($scope.products, $scope.search);
       // $scope.totalItems = $scope.filteredProducts.length;
   //});

   }])

我的服务

angular.module('gemStoreApp.productService',['ngResource'])
    .factory('productsService', function(Restangular) {
        return Restangular.service('products');
    });

我的产品控制器

angular.module('gemStoreApp')
    .controller('ProductsCtrl', ['$scope', 'productsService', function ($scope, productsService) {
        $scope.products = {};
        productsService.getList().then(function(products){
            $scope.products = products;
        });
    }]);

在我的app.js文件中添加了Restangular setRestangularFieldssetRequestInterceptor方法,这使得搜索/过滤功能正常工作,但我仍然收到Expected array but received {}错误

RestangularProvider.setRestangularFields({
  id: '_id.$oid'
});

RestangularProvider.setRequestInterceptor(function(elem, operation) {

  if (operation === 'put') {
    elem._id = undefined;
    return elem;
  }
  return elem;
});

我创建了一个看似正常工作的Plunker版本。 Plunker example

创建了一个更新的Plunker,其中包含我看到的本地问题。问题是分页无法正常工作。它只显示我想要的10个项目,但点击这两个项目不会切换到第2页。Plunker example

1 个答案:

答案 0 :(得分:0)

我在你的例子中看到了一些错误。我相信你的html中不需要ng-controller =“SearchCtrl”。 此外,在ng重复中使用过滤器的要点是不使用搜索文本输入的监视事件。因此,您应该使用products数组并对其应用过滤器。如果你想使用filteredProducts,我在下面的例子中留下了一个函数。我初始化变量,因为我无法访问你的不安分api。

var app = angular.module('myApp', []);
app.filter('startFrom', function() {
    return function(input, start) {
        if(input) {
            start = +start; //parse to int
            return input.slice(start);
        }
        return [];
    }
});

app.controller('paginationCtrl', ['$scope', '$log', '$filter', function ($scope, $log, $filter) {
   $scope.search = {name: "Product"}
   $scope.products = [{"_id": "0000000", "name":"Product", "description": "Product Description"},
   {"_id": "0000000", "name":"Product 2", "description": "Product Description 2"}];
      $scope.filteredProducts = [];
  
   $scope.currentPage = 2;
   $scope.maxSize = 100;
   $scope.itemsPerPage = 10;
   $scope.startFrom = ($scope.currentPage - 1) * $scope.itemsPerPage;
   var filterProducts = function(newVal){
        $scope.filteredProducts.splice(0, $scope.filteredProducts.length);
         angular.forEach($scope.products, function(product) {
           if(product.name == newVal){
            $scope.filteredProducts.push(product);  
           }
       });
   }
   $scope.$watch('search.name', function(newVal, oldVal) {
        filterProducts(newVal);
       $scope.totalItems = $scope.filteredProducts.length;
   }, true);
   
    $scope.$watch('currentPage', function(newVal, oldVal) {
        $scope.startFrom = ($scope.currentPage - 1) * $scope.itemsPerPage;
   }, true);
    $scope.$watch('itemsPerPage', function(newVal, oldVal) {
       $scope.startFrom = ($scope.currentPage - 1) * $scope.itemsPerPage;
   }, true);
  

   }])
<!DOCTYPE html>
<html>

  <head>
    <script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    
   <div ng-app="myApp">
            
     <div ng-controller="paginationCtrl as ctrl" class="row">
      
    <div class="col-lg-12">   
        <div class="pull-left">
                <div class="input-group product-searchs" >
                    <label class="sr-only" for="searchProducts">Search</label>
                    <span class="input-group-addon search-icon"><i class="fa fa-search" aria-hidden="true"></i></span>
                    <input type="text" class="form-control" ng-model="search.name" placeholder="Search for products" />
                    <span class="input-group-addon clear-icon">
                        <button type="button" ng-click="clearSearch()">
                            <i class="glyphicon glyphicon-remove" aria-hidden="true">test</i>
                        </button>
                    </span>       
                </div>           
            
        </div>
    </div>
    <div class="col-lg-12">
        <div class="list-group">
            <a ui-sref="productDetails({id:product._id})"  class="list-group-item clearfix" ng-repeat="product in products | filter: search.name  | limitTo: itemsPerPage | startFrom: 0  ">
                {{product.name}} 
                {{product.description}}
                <br/>
            </a>
        </div>
    </div>
    <div class="col-lg-12">
        <pagination class="pull-right" page="currentPage" total-items="totalItems" ng-model="currentPage" max-size="maxSize" ng-change="pageChanged()" items-per-page="itemsPerPage" num-pages="numPages"></pagination>
    </div>
</div>

</div>

  </body>

</html>

修改 在观察您的plunker之后,您不需要将filteredProducts添加到控制器,因为您正在视图中进行过滤。通过将filteredProducts添加到视图中,还可以使用$ scope.filteredProducts在控制器中访问它。 因此,使用下面的代码替换html的底部,并删除处理来自控制器的filteredProducts的所有代码:

<div class="col-lg-12">
          <div class="list-group">
            <a ui-sref="productDetails({id:product._id})" class="list-group-item clearfix" ng-repeat="product in filteredProducts = (products | filter: search.name | limitTo: itemsPerPage | startFrom: 0)  ">
              {{product.name}}<br/>
              {{product.description}}
            </a>
          </div>
        </div>
        <div class="col-lg-12">
          <pagination class="pull-right" page="currentPage" total-items="filteredProducts.length" ng-model="currentPage" max-size="maxSize" ng-change="pageChanged()" items-per-page="itemsPerPage" num-pages="numPages"></pagination>
        </div>

如果您想手动完成所有操作(我不建议这样做),您必须将html更改为filteredProducts中的产品,当它开始将所有产品添加到filteredProducts列表并将您的代码保存在控制器中时。此外,当搜索为空时,您将不得不再次填充filteredProducts列表。