問題描述
ng‑repeat 加載後不顯示表行 (ng‑repeat not showing table rows after loading)
我遇到了一些問題,使用 ng‑repeat 沒有顯示任何數據。
流程如下
我在從服務器請求數據之前調用了一個 sharedObjects 服務,以防萬一所需的數據已經加載並可用。
加載部分工作,並顯示在控制台中。出於測試目的設置了超時,並且頁面保持在加載視圖中,直到加載數據。但是這些行沒有第一次出現。轉到另一個頁面並返回有問題的頁面後,數據顯示正常,並且是從 sharedObjects 服務加載的。
我的代碼如下
// dataService aka sharedObjects
angular.module('app').factory('dataService', function(){
var List = undefined;
return {
getList: function () {
return List;
},
setList: function (list) {
List = list;
},
}
});
// controller
angular.module('appWebmenu').controller('appWebmenuController', ['$scope', 'dataService', 'webmenuService', function($scope, dataService, webmenuService){
$scope.listLoaded = false; // data is not loaded flag
$scope.listError = false; // no errors occured yet flag
// function to load and pass the data to the ng‑repeat
$scope.getItemList = function(){
// trying for preloaded data
$scope.itemList = dataService.getList();
console.log($scope.itemList);
if($scope.itemList === undefined){
// data not previously loaded get from server (service)
$scope.itemList = webmenuService.getWebmenuList($scope.shop_id,$scope.token)
// after data loads promise returned
.then(
// on success
function(data){
// by adding the extra call to the dataService, it works. Brilliant
$scope.itemList = dataService.getList();
$scope.listLoaded = true; // set the data as loaded
return data;
},
// on failure
function(data){
$scope.listLoaded = false; // data still not loaded
$scope.listError = true; // an error has occured
alert(data.errorMessage);
});
}
else{
$scope.listLoaded = true; // data returned from preloaded dataService
}
return $scope.itemList;
};
// dataRetrieval which connects to the server
angular.module('appWebmenu').factory('webmenuService', ['$q','$http', 'dataService','$timeout', function($q, $http, dataService, $timeout){
return {
getWebmenuList: function (shop_id, token) {
var dfr = $q.defer(); // init promise
// set retrieval settings
var req = {
method: 'POST',
url: "../api/v1/Webmenu/menulist/all",
headers: {
'Content‑Type': 'application/json'
},
data: {shop_id: '' + shop_id,token: '' + token }
};
// execute retrieval request
$http(req)
// when loaded
.then(
// on success
function(response){
dataService.setList(response.data); // setting the data to the dataService for reuse
$timeout(function(){
dfr.resolve(response.data);
},5000);
},
// on failure
function(response){
dfr.reject( false );
});
return dfr.promise;
}
};
}]);
// directive
angular.module('appWebmenu').directive('appWebmenuList', function() {
return {
//require: '^appWebmenu',
transclude: true,
templateUrl: 'external/appWebmenu/appWebmenuListTemplate.html',
controller: 'appWebmenuController',
scope: {
},
link: function(scope, el, attr, ctrl) {
}
}
});
// Template
<!‑‑ to show while loading ‑‑>
<div ng‑if="!listLoaded"> // corresponds with $scope.listLoaded in the controller
<i class="fa fa‑spinner fa‑spin fa‑3x"></i>
</div>
<!‑‑show when an error occures‑‑>
<div ng‑if="listError"> // corresponds with $scope.listError in the controller
{{ 'ERROR_LOADING' | translate }}
</div>
<!‑‑ show when data is loaded and no errors occured‑‑>
<div ng‑if="listLoaded && !listError && itemList"> // check if list is loaded, no errors occured and if itemList is not empty or undefined
<table class="webmenu‑table‑main">
<thead>
<tr>
<th>{{'PAGE' | translate}}</th>
<th>{{'ACTIONS' | translate}}</th>
</tr>
</thead>
<tbody>
<tr ng‑repeat="item in itemList">
<script>console.log('menu name is {{ item.menu_name }}');</script>
<td>{{item.menu_name}}</td>
<td>
<i class="fa fa‑search" title="{{ 'DETAILS' | translate }}" ng‑click="details(item.menu_id)" ng‑if="item.menu_is_editable != '0'"></i>
<i class="fa fa‑pensil‑square" title="{{ 'EDIT' | translate }}" ng‑click="edit(item.menu_id)" ng‑if="item.menu_is_editable != '0'"></i>
<i class="fa fa‑trash‑o" title="{{ 'DELETE' | translate }}" ng‑click="remove(item.menu_id)" ng‑if="item.menu_is_editable != '0'"></i>
<i class="fa fa‑plus" title="{{ 'ADDMENU' | translate }}" ng‑click="addNewMenuItem(item.menu_id)"></i>
<i class="fa fa‑external‑link‑square" title="{{ 'OPENEDITOR' | translate }}" ng‑click="openInEditor(item.menu_id)" ng‑if="item.menu_is_editable != '0'"></i>
</td>
</tr>
</tbody>
</table>
</div>
我有什麼遺漏嗎?這僅適用於第一次預加載數據之後的時間。
參考解法
方法 1:
webmenuService.getWebmenuList returns a promise. Not data. You need to set $scope.itemList inside your then
function call.
if($scope.itemList === undefined){
// data not previously loaded get from server (service)
var qListPromise = webmenuService.getWebmenuList($scope.shop_id,$scope.token)
// after data loads promise returned
.then(
// on success
function(data){
$scope.listLoaded = true; // set the data as loaded
return data;
},
// on failure
function(data){
$scope.listLoaded = false; // data still not loaded
$scope.listError = true; // an error has occured
alert(data.errorMessage);
});
qListPromise.then( function(data) { $scope.itemList = data;
}).catch( function(error) { throw error; });
(by sillysicko、georgeawg)