如何使用角UI选项卡和UI网格重新绘制表?

时间:2021-10-02 11:05:13

I'm trying to migrate from jQuery Data Tables to Angular UI. My app uses the 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. In Angular, I created 3 tabs, clicking on each of which is supposed to reload the page with a new grid and populate it with data. Problem is, the grid gets displayed alright on page load with the content on the first tab. On clicking the other tabs, page goes empty and nothing is rendered. Now the data returned is not insignificant, sometimes around 4k rows. However, the problem isn't a latency issue as I've confirmed by waiting several minutes.

我正在尝试从jQuery数据表迁移到角度UI。我的应用程序使用MySQL World模式,并在3个不同的表中显示数据。在jQuery中,我有3个不同的页面,每个都是从一个主页启动的。这是一个生活的例子。在“角度”中,我创建了3个选项卡,单击其中的每个选项卡,应该使用新的网格重新加载页面并填充数据。问题是,网格在页面加载时显示正常,第一个选项卡上的内容也显示正常。单击其他选项卡时,页面为空,不会呈现任何内容。现在返回的数据不是不重要的,有时大约是4k行。但是,这个问题并不是延迟问题,因为我已经等了几分钟。

I'm not a JS/CSS/HTML guy so most likely I'm missing something. That's why this question.

我不是一个JS/CSS/HTML的家伙,所以我很可能漏掉了什么。这就是为什么这个问题。

Edit: Plnkr URL: http://plnkr.co/edit/6VKTDbfQgdg9l94vFPfo?p=info

编辑:Plnkr URL:http://plnkr.co/edit/6VKTDbfQgdg9l94vFPfo?p=info

Following is the code:

下面是代码:

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 id="data-panel" class="data-panel" ui-grid="gridOptions"></div>
            </uib-tab>
        </uib-tabset>
    </div>
</div>
<script src="js/app.js"></script>
</body>

JS:

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;
            });
        };
    }]);
})();

3 个解决方案

#1


1  

I see 2 problems here:

我在这里看到两个问题:

  1. You are creating/changing gridOptions dinamically. This is not the usual way of doing things and can bring many problems.

    您正在创建/更改网格选项。这不是通常的做事方式,会带来很多问题。

  2. You are using grids inside of uib-tabs and this, like uib-modals, can have some annoying side effects.

    您正在使用uibtab中的网格,这就像uibt -modals一样,会有一些恼人的副作用。

I'd suggest you to address the first issue using different gridOptions (as you do when you create them) and then putting them inside your tabs array children, this way you can refer them from the html this whay:

我建议您使用不同的gridOptions来解决第一个问题(就像您创建它们时所做的那样),然后将它们放在选项卡数组子元素中,这样您就可以从html中引用它们了。

<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>

The second problem is quite known and inside this tutorial they explain how to address it: you should add a $interval instruction to refresh the grid for some time after it's updated in order to let the tab take its time to load and render.

第二个问题是众所周知的,在本教程中,他们解释了如何解决这个问题:您应该添加$interval指令,以便在网格更新后刷新一段时间,以便让选项卡能够花时间加载和呈现。

The code should be as follows:

代码应如下:

$scope.tabs[0].gridOptions.data = data; 
$interval( function() {
  $scope.gridCountriesApi.core.handleWindowResize();
}, 10, 500);

Where gridCountriesApi are created inside of a regular onRegisterApi method.

在一个常规的onRegisterApi方法中创建gridcountries的api。

I edited your plunkr, so you can see the whole code.

我编辑了你的普兰克,所以你可以看到整个代码。

#2


1  

I can not get this to work in tabs, my guess is because you first use ng-repeat which creates a scope for each iteration, and then maybe the tabs itself creates a new scope and this causes a lot of headache with updates.

我无法让它在制表符中工作,我猜是因为您首先使用ng-repeat,它为每次迭代创建一个范围,然后制表符本身可能创建一个新的范围,这在更新中会引起很多麻烦。

The quickest solution is just to move the grid outside of the tabs.

最快的解决方案是将网格移到制表符之外。

Here is the updated html.

这是更新后的html。

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>

#3


0  

In my situation tab contents consume important time to be loaded. So if your case is that you don't want to update tab content everytime the tab is clicked, you can use this workaround:

在我的情况下,标签的内容会占用重要的加载时间。如果你的情况是你不想每次点击tab后更新tab内容,你可以使用这个方法:

In the HTML part I use select property to indicate which tab is pressed:

在HTML部分,我使用select属性来指示按下哪个选项卡:

<tabset justified="true">
    <tab heading="Tab 1" select="setFlag('showTab1')">
        <div ng-if="showTab1">
        ...
        </div>
    </tab>
</tabset>

In the tab (*) container I used a switch to recognize which tab is pressed and broadcast the press action:

在选项卡(*)容器中,我使用了一个开关来识别按下哪个选项卡并广播按下动作:

case 'showTab1':
    $scope.$broadcast('tab1Selected');
    break;

And in the controller part I listen the event and handle resizing:

在控制器部分,我监听事件并处理调整大小:

// 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);
});

Here is my Plunkr. Hope it helps.

这是我的Plunkr。希望它可以帮助。

(*) For current bootstrap version you should use and

(*)对于当前的引导版本,您应该使用and

#1


1  

I see 2 problems here:

我在这里看到两个问题:

  1. You are creating/changing gridOptions dinamically. This is not the usual way of doing things and can bring many problems.

    您正在创建/更改网格选项。这不是通常的做事方式,会带来很多问题。

  2. You are using grids inside of uib-tabs and this, like uib-modals, can have some annoying side effects.

    您正在使用uibtab中的网格,这就像uibt -modals一样,会有一些恼人的副作用。

I'd suggest you to address the first issue using different gridOptions (as you do when you create them) and then putting them inside your tabs array children, this way you can refer them from the html this whay:

我建议您使用不同的gridOptions来解决第一个问题(就像您创建它们时所做的那样),然后将它们放在选项卡数组子元素中,这样您就可以从html中引用它们了。

<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>

The second problem is quite known and inside this tutorial they explain how to address it: you should add a $interval instruction to refresh the grid for some time after it's updated in order to let the tab take its time to load and render.

第二个问题是众所周知的,在本教程中,他们解释了如何解决这个问题:您应该添加$interval指令,以便在网格更新后刷新一段时间,以便让选项卡能够花时间加载和呈现。

The code should be as follows:

代码应如下:

$scope.tabs[0].gridOptions.data = data; 
$interval( function() {
  $scope.gridCountriesApi.core.handleWindowResize();
}, 10, 500);

Where gridCountriesApi are created inside of a regular onRegisterApi method.

在一个常规的onRegisterApi方法中创建gridcountries的api。

I edited your plunkr, so you can see the whole code.

我编辑了你的普兰克,所以你可以看到整个代码。

#2


1  

I can not get this to work in tabs, my guess is because you first use ng-repeat which creates a scope for each iteration, and then maybe the tabs itself creates a new scope and this causes a lot of headache with updates.

我无法让它在制表符中工作,我猜是因为您首先使用ng-repeat,它为每次迭代创建一个范围,然后制表符本身可能创建一个新的范围,这在更新中会引起很多麻烦。

The quickest solution is just to move the grid outside of the tabs.

最快的解决方案是将网格移到制表符之外。

Here is the updated html.

这是更新后的html。

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>

#3


0  

In my situation tab contents consume important time to be loaded. So if your case is that you don't want to update tab content everytime the tab is clicked, you can use this workaround:

在我的情况下,标签的内容会占用重要的加载时间。如果你的情况是你不想每次点击tab后更新tab内容,你可以使用这个方法:

In the HTML part I use select property to indicate which tab is pressed:

在HTML部分,我使用select属性来指示按下哪个选项卡:

<tabset justified="true">
    <tab heading="Tab 1" select="setFlag('showTab1')">
        <div ng-if="showTab1">
        ...
        </div>
    </tab>
</tabset>

In the tab (*) container I used a switch to recognize which tab is pressed and broadcast the press action:

在选项卡(*)容器中,我使用了一个开关来识别按下哪个选项卡并广播按下动作:

case 'showTab1':
    $scope.$broadcast('tab1Selected');
    break;

And in the controller part I listen the event and handle resizing:

在控制器部分,我监听事件并处理调整大小:

// 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);
});

Here is my Plunkr. Hope it helps.

这是我的Plunkr。希望它可以帮助。

(*) For current bootstrap version you should use and

(*)对于当前的引导版本,您应该使用and