AngularJS ngTable 延迟显示 ajax 数据
Posted
技术标签:
【中文标题】AngularJS ngTable 延迟显示 ajax 数据【英文标题】:AngularJS ngTable delays display of ajax data 【发布时间】:2014-04-21 04:37:11 【问题描述】:背景
我正在努力解决使用ngTable 的细节问题。我浏览了ngTable ajax demo 并尝试尽可能合理地遵循该示例;但是,我需要偏离 ngTable ajax demo 定义与控制器内联的 ngResource 的部分。
问题
我用ngTable filters成功构建了一个ngTable;我的 webapp 是 here(另见 plunker)。这是一个 ngTable:
从json REST service 加载数据 从 json 数据构建 ngTable 分类 过滤器json REST service 正确加载,过滤器正常工作。但是,我的问题是表格是空白的,直到我在“过滤器”字段中输入内容(请参阅下面的 before 和 after 屏幕截图)。
我试过的所有浏览器都存在这个问题:
Firefox 27.0.1 (Windows Vista) Chrome 版本 33.0.1750.146 (Windows Vista) Chrome 版本 32.0.1700.123 (Linux - Debian 7.0 Wheezy)我知道 webapp 在 Internet Exploder 9 中被破坏了......我不知道为什么,但我真的不关心 IE;这个 webapp 不会成为公共 web 服务。
问题
如何在第一次加载 my webapp 时填充表格(不在过滤框中输入任何内容)? 为什么现在坏了?注意:源代码在页面底部...我为它构建了一个plunker。
尾注
注意 1眼尖的读者可能会注意到,我在 AngularJS 表单中使用了 [[
和 ]]
的默认花括号分隔符。我这样做是因为我将Flask 与Jinja 一起使用(它的模板引擎也需要双花括号)。.
屏幕截图
之前:页面在我加载时是空白的:
之后:但是,如果我在过滤器中键入任何字符,ngTable 会显示数据:
更新:明确的问题解决,感谢 lib3d 的回答
<script type="text/javascript">
"use strict";
// Set up an ngResource service to make HTTP GET / POST / DELETE calls
var Api = angular.module("api_main", ["ngResource"]);
Api.factory("restDemo", function ($resource)
// http://www.masnun.com/2013/08/28/rest-access-in-angularjs-using-ngresource.html
return $resource("http://demo.pennington.net/demo/api/v1/data01", , );
);
// Loosely based on this ngTable demo...
// http://bazalt-cms.com/ng-table/example/6
var App2 = angular.module('taskTable', ['ngRoute', 'api_main',
'ngTable']);
// Need to change AngularJS symbols when using flask + Jinja
App2.config(function($interpolateProvider)
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
);
App2.controller('tableCntl', function($scope, $filter, restDemo, ngTableParams)
var data = restDemo.query(); // HTTP GET for REST service
// Set up task table parameters
/* Lib3d's fix (i.e. data.$promise) is below */
data.$promise.then(function (data)
/* the data is here, work with it */
$scope.tableParams = new ngTableParams(
page: 1, // show first page
count: 10, // count per page
total: data.length,
sorting:
Column01: 'asc',
Column02: 'asc',
Column03: 'asc'
,
filter:
Column01: "",
Column02: "",
Column03: "",
,
getData: function($defer, params)
// Filtering
var orderedData = params.filter() ?
$filter('filter')(data, params.filter()) :
data;
// Sorting
orderedData = params.sorting() ?
$filter('orderBy')(orderedData, params.orderBy()) :
orderedData;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
/* set total for recalc pagination */
params.total(orderedData.length);
// This shouldn't be required, but keeping here in case
//if(!$scope.$$phase)
// $scope.$apply();
//
);
);
);
</script>
破解的demo源码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="description" content="">
<meta name="author" content="">
<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.4.2/pure-min.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/angular.ngtable/0.3.1/ng-table.css">
<!--
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css">
<link rel="stylesheet" type="text/css" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables.css">
-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body
padding-top: 30px; /* 30px pad at the top of screen */
</style>
<!-- Fix up title -->
<title>DATA DEMO</title>
</head>
<body>
<div class="pure-g">
</div>
<!-- Static navbar -->
<div class="pure-g">
<div id="menu" class="pure-u">
<div class="pure-menu pure-menu-horizontal pure-menu-open">
<ul>
<li><a href="#">Add Demo</a></li>
<li class="active"><a href="#">List Demo</a></li>
<li><a href="#">List Projects</a></li>
<li>
<a href="/login">Login</a>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
<!--- insert stuff here -->
<div id="Tasks" ng-app="taskTable" ng-controller="tableCntl">
<p><strong>Filter:</strong> [[tableParams.filter()|json]]
<table ng-table="tableParams" show-filter="true" class="table">
<tbody>
<tr ng-repeat="words in $data">
<td data-title="'Column01'" sortable="Column01" filter="'Column01': 'text'">
[[words.Column01]]
</td>
<td data-title="'Column02'" sortable="Column02" filter="'Column02': 'text'">
[[words.Column02]]
</td>
<td data-title="'Column03'" sortable="Column03" filter="'Column03': 'text'">
[[words.Column03]]
</td>
</tr>
</tbody>
</table>
</div>
</body>
<!-- insert JS at the bottom of the page -->
<footer>
<!-- all flash messages are processed here -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular-route.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular-resource.min.js"></script>
<script type="text/javascript" src="//cdn.jsdelivr.net/angular.ngtable/0.3.1/ng-table.js"></script>
<!--
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.min.js"></script>
-->
<script type="text/javascript">
"use strict";
// Set up an ngResource service to make HTTP GET / POST / DELETE calls
var Api = angular.module("api_main", ["ngResource"]);
Api.factory("restDemo", function ($resource)
// http://www.masnun.com/2013/08/28/rest-access-in-angularjs-using-ngresource.html
return $resource("http://demo.pennington.net/demo/api/v1/data01", , );
);
// Loosely based on this ngTable demo...
// http://bazalt-cms.com/ng-table/example/6
var App2 = angular.module('taskTable', ['ngRoute', 'api_main',
'ngTable']);
// Need to change AngularJS symbols when using flask + Jinja
App2.config(function($interpolateProvider)
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
);
App2.controller('tableCntl', function($scope, $filter, restDemo, ngTableParams)
var data = restDemo.query(); // HTTP GET for REST service
// Set up task table parameters
$scope.tableParams = new ngTableParams(
page: 1, // show first page
count: 10, // count per page
total: data.length,
sorting:
Column01: 'asc',
Column02: 'asc',
Column03: 'asc'
,
filter:
Column01: "",
Column02: "",
Column03: "",
,
getData: function($defer, params)
// use build-in angular filter
var orderedData = params.filter() ?
$filter('filter')(data, params.filter()) :
data;
//sorting
orderedData = params.sorting() ?
$filter('orderBy')(orderedData, params.orderBy()) :
orderedData;
// store filtered data as $scope.words
$scope.words = orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count());
params.total(orderedData.length); // set total for recalc pagination
$defer.resolve($scope.words);
$defer.resolve(data.result);
);
);
</script>
<!-- Custom footer content here -->
</footer>
</html>
数据(我会在回答完问题后删除demojson REST service):
["Column02": "shines", "Column03": "paycheck", "Column01": "days",
"Column02": "erg", "Column03": "gag", "Column01": "emotion's",
"Column02": "Chris", "Column03": "Poznan's", "Column01": "treasure's",
"Column02": "presentiments", "Column03": "Austerlitz's", "Column01": "suppression's",
"Column02": "leopards", "Column03": "slosh's", "Column01": "upturned",
"Column02": "uncaring", "Column03": "cosmetics", "Column01": "symmetry",
"Column02": "guesser's", "Column03": "lapped", "Column01": "retrogressed",
"Column02": "Kurd", "Column03": "wryest", "Column01": "cicadas",
"Column02": "cantered", "Column03": "encrustation's", "Column01": "beyond",
"Column02": "flybys", "Column03": "poesying", "Column01": "physician's",
"Column02": "fun", "Column03": "Delaware's", "Column01": "destructiveness",
"Column02": "scramblers", "Column03": "gestates", "Column01": "acoustics",
"Column02": "redesigning", "Column03": "cubits", "Column01": "Enterprise",
"Column02": "phonograph's", "Column03": "haloed", "Column01": "upsurge",
"Column02": "Michelson", "Column03": "Pansy", "Column01": "McCoys",
"Column02": "adieu", "Column03": "Dido", "Column01": "ligaturing",
"Column02": "osprey's", "Column03": "expressiveness's", "Column01": "Starr",
"Column02": "patent's", "Column03": "therapeutically", "Column01": "brasher",
"Column02": "enfranchise", "Column03": "idolized", "Column01": "criticized",
"Column02": "Angel", "Column03": "wryest", "Column01": "drum",
"Column02": "overstaying", "Column03": "tranquillized", "Column01": "alacrity",
"Column02": "underachievers", "Column03": "minority", "Column01": "Brigham's",
"Column02": "lobotomy's", "Column03": "filament's", "Column01": "scoldings",
"Column02": "original", "Column03": "muskmelon's", "Column01": "financially",
"Column02": "flagon's", "Column03": "vapidness", "Column01": "Klaus's",
"Column02": "dhotis", "Column03": "fleeter", "Column01": "jugulars",
"Column02": "shanty", "Column03": "profiteer's", "Column01": "disbelief",
"Column02": "bureaucracies", "Column03": "flashier", "Column01": "refrigerating",
"Column02": "betrayal's", "Column03": "hindquarters", "Column01": "faze",
"Column02": "Poland", "Column03": "cobbler", "Column01": "kidnaped"]
我正在使用...
Yahoo PureCSS 0.4.2版 jQuery 2.0.3 版 AngularJS 版本 1.2.14注 1我已经尝试过的
这些事情似乎都没有对问题产生影响:
删除 jQuery 删除Yahoo PureCSS 更改ngTable Filters 上的默认值 从页面中删除所有其他 javascript(这实际上在同一页面上有多个 AngularJS 控制器,但删除了所有其他控制器,希望这只是一个简单的脚本冲突。 在构建 ngTable 的 AngularJS 控制器中进行了几个实验性的what-if-I-modify-this(阅读:抓住稻草)。 尝试在我的过滤器中使用null
而不是空字符串,如suggested by Sander Elias
如果我在 <script>
块内内联 json 数据而不是进行 ajax json REST service 调用,则该表会在页面加载时正确填充,但这确实无济于事,因为数据会不时更改。
【问题讨论】:
【参考方案1】:您的data
是异步获取的,但您会同步使用它。那么第一次getData
调用使用了未解析的数据,也就是说根本没有数据。
键入一个字符似乎会想起getData
,这次解析为data
。这可以解释在第一次键入的键上显示的数据。
要等待获取数据,请在此类回调中实现ngTable
调用:
/* there, data are not fetched */
data.$promise.then(function (data)
/* there data are fetched, work with it */
);
【讨论】:
不客气。这种异步数据的唯一神奇之处在于,当在模板中使用时,promise 在解析时被解包。从版本 1.2.0-rc.3 开始,您必须添加此配置:$parseProvider.unwrapPromises(true)
。但在展开之前,没有魔法发生!以上是关于AngularJS ngTable 延迟显示 ajax 数据的主要内容,如果未能解决你的问题,请参考以下文章
如何使表格中的整行像ngtable(angularjs)中的超链接(在新选项卡等中打开)一样
使用 MEAN 堆栈延迟加载 (AngularJS 1.x)