我正在尝试创建一个使用 ng-grid 和 ASP.NET WebAPI 的简单工作示例。因此,我从 ng-grid 示例页面 ( http://angular-ui.github.io/ng-grid/ ) 中的服务器端分页示例开始;无论如何,我的网格总是显示空列,即使在调试时我可以确认数据已正确接收。可能我只是在网格设置中遗漏了一些东西,但我发现的所有样本看起来都与我的相似。有人可以帮忙吗?这是我所做的:
更新#1:建议的解决方案似乎有效,但仅适用于第一页。每当我移动到新页面或执行任何其他需要刷新的操作时,即使服务器按预期返回数据更改,显示的数据也会保持不变。此外,从我发现的所有代码示例中,似乎设置数据的正确方法只是替换数组成员值,而不是清空并再次填充它。我按照https://groups.google.com/forum/#!searchin/angular/nggrid/angular/vUIfHWt4s_4/oU_C9w8j-uMJ中的建议尝试了 apply ,但得到了相同的结果。
服务器端
只需创建一个新的 MVC4 应用程序,更新 NuGet 包并添加 angular 和 ng-grid 包。我的假数据模型由 Item 类表示:
public sealed class Item
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public bool IsFemale { get; set; }
}
我还添加了几个模型来处理分页、过滤和排序各种数据集(我发现更容易拥有一个通用的分页基础模型 -PagedFilter- 和一些派生模型):
public class PagedFilter
{
private int _nPageSize;
private int _nPageNumber;
public int PageSize
{
get { return _nPageSize; }
set
{
if (value < 1) throw new ArgumentOutOfRangeException("value");
_nPageSize = value;
}
}
public int PageNumber
{
get { return _nPageNumber; }
set
{
if (value < 1) throw new ArgumentOutOfRangeException("value");
_nPageNumber = value;
}
}
public int TotalItems { get; set; }
public int TotalPages
{
get { return (int)Math.Ceiling((double)(TotalItems / PageSize)); }
}
public PagedFilter()
{
_nPageSize = 20;
_nPageNumber = 1;
}
}
这是项目过滤器:
public class ItemFilter : PagedFilter
{
public List<string> SortFields { get; set; }
public List<string> SortDirections { get; set; }
public string Name { get; set; }
public int? MinAge { get; set; }
public int? MaxAge { get; set; }
}
然后我添加一个用于获取项目的 API 控制器:
public class ItemController : ApiController
{
// fake data
private readonly List<Item> _items;
public ItemController()
{
Random rnd = new Random();
_items = new List<Item>();
char c = 'a';
for (int i = 0; i < 1000; i++)
{
_items.Add(new Item
{
Id = i,
Age = rnd.Next(1, 100),
IsFemale = ((i & 1) == 0),
Name = String.Format(CultureInfo.InvariantCulture, "{0:00000}-{1}",
i, new string(c, 5))
});
if (++c > 'z') c = 'a';
}
}
public dynamic Get([FromUri] ItemFilter filter)
{
var items = _items.AsQueryable();
// filtering
if (!String.IsNullOrEmpty(filter.Name))
items = items.Where(i => i.Name.Contains(filter.Name));
if (filter.MinAge.HasValue)
items = items.Where(i => i.Age >= filter.MinAge.Value);
if (filter.MaxAge.HasValue)
items = items.Where(i => i.Age <= filter.MaxAge.Value);
// ...sorting (using Dynamic Linq) omitted for brevity...
// paging
int nTotalItems = items.Count();
items = items.Skip((filter.PageNumber - 1) * filter.PageSize)
.Take(filter.PageSize);
return new
{
totalItems = nTotalItems,
items = items.ToArray()
};
}
}
客户端
在客户端,我的 Angular 应用程序只是在 ng-grid 示例上建模的单个控制器:因此我直接将属性添加到 $scope,即使在实际场景中我宁愿使用模型(可能从TypeScript 类)。HTML:
<div ng-app="MyApp" ng-controller="MainController">
<div ng-grid="gridOptions" style="height: 400px">
</div>
</div>
JS:
var app = angular.module('MyApp', ['ngGrid']);
app.controller('MainController', ['$scope', '$http', function ($scope, $http, $apply) {
$scope.items = [];
// filter
$scope.filterOptions = {
filterText: "",
useExternalFilter: true
};
// paging
$scope.totalServerItems = 0;
$scope.pagingOptions = {
pageSizes: [25, 50, 100],
pageSize: 25,
currentPage: 1
};
// sort
$scope.sortOptions = {
fields: ["name"],
directions: ["ASC"]
};
// grid
$scope.gridOptions = {
data: "items",
columnDefs: [
{ field: "name", displayName: "Name", pinnable: true },
{ field: "age", displayName: "Age", width: "60" },
{ field: "isFemale", displayName: "F", width: "40" }
],
enablePaging: true,
enablePinning: true,
pagingOptions: $scope.pagingOptions,
filterOptions: $scope.filterOptions,
keepLastSelected: true,
multiSelect: false,
showColumnMenu: true,
showFilter: true,
showGroupPanel: true,
showFooter: true,
sortInfo: $scope.sortOptions,
totalServerItems: "totalServerItems",
useExternalSorting: true,
i18n: "en"
};
$scope.refresh = function() {
setTimeout(function () {
var p = {
name: $scope.filterOptions.filterText,
pageNumber: $scope.pagingOptions.currentPage,
pageSize: $scope.pagingOptions.pageSize,
sortFields: $scope.sortOptions.fields,
sortDirections: $scope.sortOptions.directions
};
$http({
url: "/api/item",
method: "GET",
params: p
}).success(function(data, status, headers, config) {
$scope.totalServerItems = data.totalItems;
// SUGGESTION #1 -- empty and fill the array
/* $scope.items.length = 0;
angular.forEach(data.items, function (item) {
$scope.items.push(item);
});
*/
// https://groups.google.com/forum/#!searchin/angular/nggrid/angular/vUIfHWt4s_4/oU_C9w8j-uMJ
$scope.$apply(function () { $scope.items = data.items; });
if (!$scope.$$phase) {
$scope.$apply();
}
}).error(function(data, status, headers, config) {
alert(JSON.stringify(data));
});
}, 100);
};
// watches
$scope.$watch('pagingOptions', function (newVal, oldVal) {
if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) {
$scope.refresh();
}
}, true);
$scope.$watch('filterOptions', function (newVal, oldVal) {
if (newVal !== oldVal) {
$scope.refresh();
}
}, true);
$scope.$watch('sortOptions', function (newVal, oldVal) {
if (newVal !== oldVal) {
$scope.refresh();
}
}, true);
$scope.refresh();
}]);
在我的代码中,调用了成功回调,我可以浏览data.items中所有返回的项目。然而,网格中没有显示任何内容。控制台中没有出现错误。