如何使用 Angular UI 选项卡和 UI 网格重绘表格?
How to Redraw Tables using Angular UI Tabs and UI Grid?
我正在尝试从 jQuery 数据表迁移到 Angular UI。我的应用程序使用 MySQL World schema and displays the data in 3 different tables. In jQuery, I'd 3 different pages, each launched from a home page. Here's a live example。
在 Angular 中,我创建了 3 个选项卡,单击每个选项卡应该会使用新网格重新加载页面并用数据填充它。问题是,网格在第一个选项卡上的内容在页面加载时显示正常。单击其他选项卡时,页面变空并且不呈现任何内容。现在返回的数据不是微不足道的,有时大约 4k 行。但是,正如我通过等待几分钟确认的那样,问题不是延迟问题。
我不是 JS/CSS/HTML 人,所以很可能我遗漏了什么。这就是为什么这个问题。
编辑:
Plnkr
代码如下:
HTML:
<body>
<div id="selection-panel" class="selection-panel" ng-controller="HelloWorldCtrl">
<div>
<uib-tabset type="pills" justified="true">
<uib-tab ng-repeat="tab in tabs" heading="{{tab.title}}" select="update(tab.title)">
<div id="data-panel" class="data-panel" ui-grid="gridOptions"></div>
</uib-tab>
</uib-tabset>
</div>
</div>
<script src="js/app.js"></script>
</body>
JS:
(function() {
var app = angular.module('helloWorld', ['ui.bootstrap', 'ui.grid']);
app.controller('HelloWorldCtrl', ['$http', '$scope', function ($http, $scope) {
$scope.tabs = [
{ title: 'Countries' },
{ title: 'Cities' },
{ title: 'Languages' }
];
$scope.gridOptions = {};
$scope.gridOptions.data = [];
$scope.gridOptionsCountries = {
columnDefs: [
{ name: 'code'},
{ name: 'name'},
{ name: 'continent'},
{ name: 'region'},
{ name: 'population'}
]
};
$scope.gridOptionsCities = {
columnDefs: [
{ name: 'id'},
{ name: 'name'},
{ name: 'country'},
{ name: 'population'}
]
};
$scope.gridOptionsLanguages = {
columnDefs: [
{ name: 'country'},
{ name: 'language'}
]
};
$scope.update = function(title) {
if (title === "Countries") {
$scope.gridOptions = angular.copy($scope.gridOptionsCountries);
} else if (title === "Cities") {
$scope.gridOptions = angular.copy($scope.gridOptionsCities);
} else if (title === "Languages") {
$scope.gridOptions = angular.copy($scope.gridOptionsLanguages);
}
$http.get(title.toLowerCase()).success(function(data) {
$scope.gridOptions.data = data;
});
};
}]);
})();
我无法让它在选项卡中工作,我的猜测是因为你首先使用 ng-repeat 为每次迭代创建一个范围,然后选项卡本身可能创建一个新的范围,这会引起很多麻烦有更新。
最快的解决方案就是将网格移到选项卡之外。
这是更新后的 html。
HTML
<body>
<div id="selection-panel" class="selection-panel" ng-controller="HelloWorldCtrl">
<div>
<uib-tabset type="pills" justified="true">
<uib-tab ng-repeat="tab in tabs" heading="{{tab.title}}" select="update(tab.title)"></div>
</uib-tab>
</uib-tabset>
<!-- This is moved outside -->
<div id="data-panel" class="data-panel" ui-grid="gridOptions">
</div>
</div>
<script src="js/app.js"></script>
</body>
我在这里看到 2 个问题:
你是 creating/changing gridOptions
动态的。这不是通常的做事方式,会带来很多问题。
您正在 uib-tabs
内部使用网格,这与 uib-modals
一样可能会产生一些恼人的副作用。
我建议您使用不同的 gridOptions
来解决第一个问题(就像您创建它们时所做的那样),然后将它们放入您的 tabs
数组子项中,这样您可以参考他们来自 html 这个 whay:
<uib-tab ng-repeat="tab in tabs" heading="{{tab.title}}" select="update(tab.title)">
<div id="data-panel" class="data-panel" ui-grid="tab.gridOptions"></div>
</uib-tab>
第二个问题是众所周知的,在 this 教程中他们解释了如何解决它:您应该添加一个 $interval
指令在网格更新后刷新一段时间,以便让选项卡需要时间来加载和呈现。
代码应该如下:
$scope.tabs[0].gridOptions.data = data;
$interval( function() {
$scope.gridCountriesApi.core.handleWindowResize();
}, 10, 500);
其中 gridCountriesApi
是在常规 onRegisterApi
方法中创建的。
我编辑了你的 plunkr,所以你可以看到完整的代码。
在我的情况下,选项卡内容会占用重要的加载时间。因此,如果您不想在每次单击选项卡时都更新选项卡内容,则可以使用此解决方法:
在 HTML 部分,我使用 select 属性 来指示按下了哪个选项卡:
<tabset justified="true">
<tab heading="Tab 1" select="setFlag('showTab1')">
<div ng-if="showTab1">
...
</div>
</tab>
</tabset>
在选项卡 (*) 容器中,我使用了一个开关来识别按下了哪个选项卡并广播了按下操作:
case 'showTab1':
$scope.$broadcast('tab1Selected');
break;
在控制器部分,我监听事件并处理调整大小:
// The timeout 0 function ensures that the code is run zero milliseconds after angular has finished processing the document.
$scope.$on('tab1Selected', function () {
$timeout(function() {
$scope.gridApi1.core.handleWindowResize();
}, 0);
});
这是我的 Plunkr。希望对你有帮助。
(*) 对于当前的 bootstrap 版本,您应该使用
我正在尝试从 jQuery 数据表迁移到 Angular UI。我的应用程序使用 MySQL World schema and displays the data in 3 different tables. In jQuery, I'd 3 different pages, each launched from a home page. Here's a live example。 在 Angular 中,我创建了 3 个选项卡,单击每个选项卡应该会使用新网格重新加载页面并用数据填充它。问题是,网格在第一个选项卡上的内容在页面加载时显示正常。单击其他选项卡时,页面变空并且不呈现任何内容。现在返回的数据不是微不足道的,有时大约 4k 行。但是,正如我通过等待几分钟确认的那样,问题不是延迟问题。
我不是 JS/CSS/HTML 人,所以很可能我遗漏了什么。这就是为什么这个问题。
编辑: Plnkr
代码如下:
HTML:
<body>
<div id="selection-panel" class="selection-panel" ng-controller="HelloWorldCtrl">
<div>
<uib-tabset type="pills" justified="true">
<uib-tab ng-repeat="tab in tabs" heading="{{tab.title}}" select="update(tab.title)">
<div id="data-panel" class="data-panel" ui-grid="gridOptions"></div>
</uib-tab>
</uib-tabset>
</div>
</div>
<script src="js/app.js"></script>
</body>
JS:
(function() {
var app = angular.module('helloWorld', ['ui.bootstrap', 'ui.grid']);
app.controller('HelloWorldCtrl', ['$http', '$scope', function ($http, $scope) {
$scope.tabs = [
{ title: 'Countries' },
{ title: 'Cities' },
{ title: 'Languages' }
];
$scope.gridOptions = {};
$scope.gridOptions.data = [];
$scope.gridOptionsCountries = {
columnDefs: [
{ name: 'code'},
{ name: 'name'},
{ name: 'continent'},
{ name: 'region'},
{ name: 'population'}
]
};
$scope.gridOptionsCities = {
columnDefs: [
{ name: 'id'},
{ name: 'name'},
{ name: 'country'},
{ name: 'population'}
]
};
$scope.gridOptionsLanguages = {
columnDefs: [
{ name: 'country'},
{ name: 'language'}
]
};
$scope.update = function(title) {
if (title === "Countries") {
$scope.gridOptions = angular.copy($scope.gridOptionsCountries);
} else if (title === "Cities") {
$scope.gridOptions = angular.copy($scope.gridOptionsCities);
} else if (title === "Languages") {
$scope.gridOptions = angular.copy($scope.gridOptionsLanguages);
}
$http.get(title.toLowerCase()).success(function(data) {
$scope.gridOptions.data = data;
});
};
}]);
})();
我无法让它在选项卡中工作,我的猜测是因为你首先使用 ng-repeat 为每次迭代创建一个范围,然后选项卡本身可能创建一个新的范围,这会引起很多麻烦有更新。
最快的解决方案就是将网格移到选项卡之外。
这是更新后的 html。
HTML
<body>
<div id="selection-panel" class="selection-panel" ng-controller="HelloWorldCtrl">
<div>
<uib-tabset type="pills" justified="true">
<uib-tab ng-repeat="tab in tabs" heading="{{tab.title}}" select="update(tab.title)"></div>
</uib-tab>
</uib-tabset>
<!-- This is moved outside -->
<div id="data-panel" class="data-panel" ui-grid="gridOptions">
</div>
</div>
<script src="js/app.js"></script>
</body>
我在这里看到 2 个问题:
你是 creating/changing
gridOptions
动态的。这不是通常的做事方式,会带来很多问题。您正在
uib-tabs
内部使用网格,这与uib-modals
一样可能会产生一些恼人的副作用。
我建议您使用不同的 gridOptions
来解决第一个问题(就像您创建它们时所做的那样),然后将它们放入您的 tabs
数组子项中,这样您可以参考他们来自 html 这个 whay:
<uib-tab ng-repeat="tab in tabs" heading="{{tab.title}}" select="update(tab.title)">
<div id="data-panel" class="data-panel" ui-grid="tab.gridOptions"></div>
</uib-tab>
第二个问题是众所周知的,在 this 教程中他们解释了如何解决它:您应该添加一个 $interval
指令在网格更新后刷新一段时间,以便让选项卡需要时间来加载和呈现。
代码应该如下:
$scope.tabs[0].gridOptions.data = data;
$interval( function() {
$scope.gridCountriesApi.core.handleWindowResize();
}, 10, 500);
其中 gridCountriesApi
是在常规 onRegisterApi
方法中创建的。
我编辑了你的 plunkr,所以你可以看到完整的代码。
在我的情况下,选项卡内容会占用重要的加载时间。因此,如果您不想在每次单击选项卡时都更新选项卡内容,则可以使用此解决方法:
在 HTML 部分,我使用 select 属性 来指示按下了哪个选项卡:
<tabset justified="true">
<tab heading="Tab 1" select="setFlag('showTab1')">
<div ng-if="showTab1">
...
</div>
</tab>
</tabset>
在选项卡 (*) 容器中,我使用了一个开关来识别按下了哪个选项卡并广播了按下操作:
case 'showTab1':
$scope.$broadcast('tab1Selected');
break;
在控制器部分,我监听事件并处理调整大小:
// The timeout 0 function ensures that the code is run zero milliseconds after angular has finished processing the document.
$scope.$on('tab1Selected', function () {
$timeout(function() {
$scope.gridApi1.core.handleWindowResize();
}, 0);
});
这是我的 Plunkr。希望对你有帮助。
(*) 对于当前的 bootstrap 版本,您应该使用