ServiceNow:表无法从服务器加载数据
ServiceNow: ngTable cannot get data to load from sever
我们的团队正在 ServiceNow 中构建一个 table 小部件,并决定尝试使用 ngTable。我们已经加载依赖项并测试它是否可以使用 github 站点上的示例正确呈现。我们现在想从名为 data.onbCase 的服务器脚本中的对象数组加载数据。但是,当我们尝试以这种方式加载数据时,我们会在控制台中收到一条错误消息:
TypeError: 无法读取未定义的 属性 'length'
在我们的客户端脚本中,我们总共有:c.onbCase.length,并且不确定为什么会产生错误。我们是不是漏掉了什么?
<div class="panel panel-default" style="margin-bottom:200px;">
<div class="panel-heading">
<span class="panel-title"><i class="fa fa-{{c.glyph}}" aria-hidden="true"></i> {{c.title}}</span>
</div>
<div class="panel-body" ng-if="c.data.loading">
<span><i class="fa fa-spinner fa-spin fa-3x fafw"></i>
<span class="sr-only">Loading...</span>
</span>
</div>
<div class="panel-body table-responsive" ng-if="!c.data.loading">
<h4 ng-if="c.options.filter">Table Filter: {{c.options.filter}}</h4>
<table id="print_table" class="display table table-striped table-hover" ng-table ="usersTable" show-filter=true>
<tr ng-click="c.onWidget('batch_qa_form_list',item.sys_id, item.short_description);"
ng-repeat="item in c.onbCase track by $index"
ng-if="item.case_visible">
<td ng-show="c.options.case_number" data-title="{{item.number}}" sortable="'number'" filter="{ 'number': 'text' }">{{item.number}}</td>
<td ng-show="c.options.last_name" data-title="{{item.last_name}}" sortable="'last_name'" filter="{ 'last_name': 'text' }">{{item.last_name}}</td>
<td ng-show="c.options.first_name" data-title="{{item.first_name}}" sortable="'first_name'" filter="{ 'first_name': 'text' }">{{item.first_name}}</td>
<td ng-show="c.options.case_short_description" data-title="{{item.short_description}}" sortable="'short_description'" filter="{ 'short_description': 'text' }">{{item.short_description}}</td>
<td ng-show="c.options.start_date" data-title="{{item.start_date}}" sortable="'start_date'" filter="{ 'start_date': 'text' }">{{item.start_date | date:'shortDate':'Z'}}</td>
<td ng-show="c.options.work_location" data-title="{{item.location}}" sortable="'location'" filter="{ 'location': 'text' }">{{item.location}}</td>
<td ng-show="c.options.form_review_status" data-title="{{item.form_review_status}}" sortable="'all_approved'" filter="{ 'all_approved': 'text' }">
<i ng-if="item.all_approved=='All Forms Reviewed'" class="fa fa-check-circle fa-lg success"></i>
<i ng-if="item.all_approved=='Pending Review'" class="fa fa-exclamation-circle fa-lg warning" uib-tooltip="{{item.number_pending}} items pending review" tooltip-placement="left" title=""></i>
</td>
</tr>
</table>
</div>
</div>
function($scope, spUtil, spModal, $filter, ngTableParams) {
var c = this;
//Set value to show loading spinner
c.data.loading = true;
function initialize() {
c.server.get({
action: 'retrieve_data'
}).then(function(response) {
//Set value to hide loading spinner
c.data.loading = false;
//Get link data
c.onbCase = response.data.onbCase;
});
}
initialize();
$scope.usersTable = new ngTableParams({
page: 1,
count: 5
}, {
total: c.onbCase.length,
getData: function ($defer, params) {
$scope.data = params.sorting() ? $filter('orderBy')(c.onbCase, params.orderBy()) : c.onbCase;
$scope.data = params.filter() ? $filter('filter')($scope.data, params.filter()) : $scope.data;
$scope.data = $scope.data.slice((params.page() - 1) * params.count(), params.page() * params.count());
$defer.resolve($scope.data);
}
});
spUtil.recordWatch($scope, "x_dnf_federal_hr_o_federal_form_review", "", function(name, data) {
initialize();
});
}
这是一个典型的不理解 JS promises 的顺序或操作的例子。您的 ngTable
初始化在数据返回之前被调用。
问题是您对 ngTableParams()
的调用是在您进行 server.get
调用之后直接进行的。在控制移动到 .then()
响应内之前,您不想 运行 这个。为此,您可以将 new ngTableParams()
调用包装在一个函数中,并在服务器调用完成时调用它。这是构建代码的正确方法:
function initialize() {
c.server.get({
action: 'retrieve_data'
}).then(function(response) {
//Set value to hide loading spinner
c.data.loading = false;
//Get link data
c.onbCase = response.data.onbCase;
// don't run the ngTable init until the http call has returned
ngTableInit();
});
}
initialize();
//wrap your ngTableParams constructor in a function
function ngTableInit() {
$scope.usersTable = new ngTableParams({
page: 1,
count: 5
}, {
total: c.onbCase.length,
getData: function ($defer, params) {
...
}
});
}
如果您在原始代码中的浏览器调试器中设置断点,您将看到 $scope.usersTable = new ngTableParams({...})
在服务器调用 returns 之前被调用,并且 c.onbCase
未定义。
我们的团队正在 ServiceNow 中构建一个 table 小部件,并决定尝试使用 ngTable。我们已经加载依赖项并测试它是否可以使用 github 站点上的示例正确呈现。我们现在想从名为 data.onbCase 的服务器脚本中的对象数组加载数据。但是,当我们尝试以这种方式加载数据时,我们会在控制台中收到一条错误消息:
TypeError: 无法读取未定义的 属性 'length'
在我们的客户端脚本中,我们总共有:c.onbCase.length,并且不确定为什么会产生错误。我们是不是漏掉了什么?
<div class="panel panel-default" style="margin-bottom:200px;">
<div class="panel-heading">
<span class="panel-title"><i class="fa fa-{{c.glyph}}" aria-hidden="true"></i> {{c.title}}</span>
</div>
<div class="panel-body" ng-if="c.data.loading">
<span><i class="fa fa-spinner fa-spin fa-3x fafw"></i>
<span class="sr-only">Loading...</span>
</span>
</div>
<div class="panel-body table-responsive" ng-if="!c.data.loading">
<h4 ng-if="c.options.filter">Table Filter: {{c.options.filter}}</h4>
<table id="print_table" class="display table table-striped table-hover" ng-table ="usersTable" show-filter=true>
<tr ng-click="c.onWidget('batch_qa_form_list',item.sys_id, item.short_description);"
ng-repeat="item in c.onbCase track by $index"
ng-if="item.case_visible">
<td ng-show="c.options.case_number" data-title="{{item.number}}" sortable="'number'" filter="{ 'number': 'text' }">{{item.number}}</td>
<td ng-show="c.options.last_name" data-title="{{item.last_name}}" sortable="'last_name'" filter="{ 'last_name': 'text' }">{{item.last_name}}</td>
<td ng-show="c.options.first_name" data-title="{{item.first_name}}" sortable="'first_name'" filter="{ 'first_name': 'text' }">{{item.first_name}}</td>
<td ng-show="c.options.case_short_description" data-title="{{item.short_description}}" sortable="'short_description'" filter="{ 'short_description': 'text' }">{{item.short_description}}</td>
<td ng-show="c.options.start_date" data-title="{{item.start_date}}" sortable="'start_date'" filter="{ 'start_date': 'text' }">{{item.start_date | date:'shortDate':'Z'}}</td>
<td ng-show="c.options.work_location" data-title="{{item.location}}" sortable="'location'" filter="{ 'location': 'text' }">{{item.location}}</td>
<td ng-show="c.options.form_review_status" data-title="{{item.form_review_status}}" sortable="'all_approved'" filter="{ 'all_approved': 'text' }">
<i ng-if="item.all_approved=='All Forms Reviewed'" class="fa fa-check-circle fa-lg success"></i>
<i ng-if="item.all_approved=='Pending Review'" class="fa fa-exclamation-circle fa-lg warning" uib-tooltip="{{item.number_pending}} items pending review" tooltip-placement="left" title=""></i>
</td>
</tr>
</table>
</div>
</div>
function($scope, spUtil, spModal, $filter, ngTableParams) {
var c = this;
//Set value to show loading spinner
c.data.loading = true;
function initialize() {
c.server.get({
action: 'retrieve_data'
}).then(function(response) {
//Set value to hide loading spinner
c.data.loading = false;
//Get link data
c.onbCase = response.data.onbCase;
});
}
initialize();
$scope.usersTable = new ngTableParams({
page: 1,
count: 5
}, {
total: c.onbCase.length,
getData: function ($defer, params) {
$scope.data = params.sorting() ? $filter('orderBy')(c.onbCase, params.orderBy()) : c.onbCase;
$scope.data = params.filter() ? $filter('filter')($scope.data, params.filter()) : $scope.data;
$scope.data = $scope.data.slice((params.page() - 1) * params.count(), params.page() * params.count());
$defer.resolve($scope.data);
}
});
spUtil.recordWatch($scope, "x_dnf_federal_hr_o_federal_form_review", "", function(name, data) {
initialize();
});
}
这是一个典型的不理解 JS promises 的顺序或操作的例子。您的 ngTable
初始化在数据返回之前被调用。
问题是您对 ngTableParams()
的调用是在您进行 server.get
调用之后直接进行的。在控制移动到 .then()
响应内之前,您不想 运行 这个。为此,您可以将 new ngTableParams()
调用包装在一个函数中,并在服务器调用完成时调用它。这是构建代码的正确方法:
function initialize() {
c.server.get({
action: 'retrieve_data'
}).then(function(response) {
//Set value to hide loading spinner
c.data.loading = false;
//Get link data
c.onbCase = response.data.onbCase;
// don't run the ngTable init until the http call has returned
ngTableInit();
});
}
initialize();
//wrap your ngTableParams constructor in a function
function ngTableInit() {
$scope.usersTable = new ngTableParams({
page: 1,
count: 5
}, {
total: c.onbCase.length,
getData: function ($defer, params) {
...
}
});
}
如果您在原始代码中的浏览器调试器中设置断点,您将看到 $scope.usersTable = new ngTableParams({...})
在服务器调用 returns 之前被调用,并且 c.onbCase
未定义。