webentwicklung-frage-antwort-db.com.de

Angular ui-grid berechnet die Höhe des Gitters dynamisch

Ich verwende: https://github.com/angular-ui/ui-grid.info/tree/gh-pages/release/3.0.0-RC.18

<div ui-grid="gridOptions" style="height:765px"></div>

Wenn ich den Wert wie oben gezeigt fest codiere, breitet sich das Raster aus und alles funktioniert wie erwartet.

Wenn ich jedoch Folgendes tue ...

$scope.gridStyle = 'height:'+numRows*rowHeight+'px' //(765px);
<div ui-grid="gridOptions" style="{{gridStyle}}"></div>

Die Höhe wird in div gedruckt und div erweitert sich, der Inhalt selbst wird jedoch nur um 340px erweitert. Der verbleibende Platz ist leer, sodass ich anstelle von 25 Zeilen nur 8 sehe. Ich muss nach unten scrollen, während im Raster ganze 400 Pixel frei sind. Sowohl das UI-Grid-Ansichtsfenster als auch das UI-Grid-Canvas verwenden diesen Raum nicht ...

Warum kann das UI-Grid-Ansichtsfenster diesen Platz nicht nutzen?

44

Ich benutze ui-grid - v3.0.0-rc.20, Weil ein Scrolling-Problem behoben ist wenn Sie die volle Höhe des Containers gehen. Verwenden Sie das Modul ui.grid.autoResize, Um die Größe des Rasters automatisch an Ihre Daten anzupassen. Verwenden Sie die folgende Funktion, um die Höhe Ihres Rasters zu berechnen. Mit ui-if Können Sie optional warten, bis Ihre Daten festgelegt wurden, bevor Sie mit dem Rendern beginnen.

angular.module('app',['ui.grid','ui.grid.autoResize']).controller('AppController', ['uiGridConstants', function(uiGridConstants) {
    ...
    
    $scope.gridData = {
      rowHeight: 30, // set row height, this is default size
      ...
    };
  
    ...

    $scope.getTableHeight = function() {
       var rowHeight = 30; // your row height
       var headerHeight = 30; // your header height
       return {
          height: ($scope.gridData.data.length * rowHeight + headerHeight) + "px"
       };
    };
      
    ...
<div ui-if="gridData.data.length>0" id="grid1" ui-grid="gridData" class="grid" ui-grid-auto-resize ng-style="getTableHeight()"></div>
76
tony

Ein einfacherer Ansatz ist die Verwendung von css in Kombination mit der dynamischen Einstellung der Werte minRowsToShow und virtualizationThreshold.

Im Stylesheet:

.ui-grid, .ui-grid-viewport {
    height: auto !important;
}

Rufen Sie im Code die folgende Funktion jedes Mal auf, wenn Sie Ihr data in gridOptions ändern. maxRowToShow ist der Wert, den Sie vordefiniert haben. Für meinen Anwendungsfall habe ich ihn auf 25 festgelegt.

ES5:

setMinRowsToShow(){
    //if data length is smaller, we shrink. otherwise we can do pagination.
    $scope.gridOptions.minRowsToShow = Math.min($scope.gridOptions.data.length, $scope.maxRowToShow);
    $scope.gridOptions.virtualizationThreshold = $scope.gridOptions.minRowsToShow ;
}
18
LeOn - Han Li

UPDATE :

Das HTML wurde angefordert, also habe ich es unten eingefügt.

<div ui-grid="gridOptions" class="my-grid"></div>

ORIGINAL :

Wir konnten dieses Problem mit responsivem CSS (@media), der die Höhe und Breite basierend auf der Bildschirmfläche festlegt. So etwas wie (und natürlich können Sie je nach Bedarf weitere hinzufügen):

@media (min-width: 1024px) {
  .my-grid {
    width: 772px;
  }
}

@media (min-width: 1280px) {
  .my-grid {
    width: 972px;
  }
}

@media (min-height: 768px) {
  .my-grid {
    height: 480px;
  }
}

@media (min-height: 900px) {
  .my-grid {
    height: 615px;
  }
}

Das Beste an dieser Lösung ist, dass wir keine Größenänderungs-Ereignisbehandlung benötigen, um Änderungen der Rastergröße zu überwachen. Es funktioniert einfach.

3
icfantv

.ui-grid, .ui-grid-viewport, .ui-grid-content-wrapper, .ui-grid-canvas {height: auto! important; }

1
Slava

Ich mag Tony Ansatz. Es funktioniert, aber ich habe mich entschieden, es anders zu implementieren. Hier meine Kommentare:

1) Ich habe einige Tests durchgeführt und bei Verwendung von ng-style Angular= wertet ng-style-Inhalt mehr als einmal aus, ich meine getTableHeight () -Funktion. Ich habe einen Haltepunkt in getTableHeight () -Funktion eingefügt, um zu analysieren Dies.

Ui-if wurde übrigens entfernt. Jetzt hast du ng-if eingebaut.

2) Ich schreibe lieber einen Service wie diesen:

angular.module('angularStart.services').factory('uiGridService', function ($http, $rootScope) {

var factory = {};

factory.getGridHeight = function(gridOptions) {

    var length = gridOptions.data.length;
    var rowHeight = 30; // your row height
    var headerHeight = 40; // your header height
    var filterHeight = 40; // your filter height

    return length * rowHeight + headerHeight + filterHeight + "px";
}
factory.removeUnit = function(value, unit) {

    return value.replace(unit, '');
}
return factory;

});

Und dann in den Controller schreiben Sie Folgendes:

  angular.module('app',['ui.grid']).controller('AppController', ['uiGridConstants', function(uiGridConstants) {

  ...

  // Execute this when you have $scope.gridData loaded...
  $scope.gridHeight = uiGridService.getGridHeight($scope.gridData);

Und in der HTML-Datei:

  <div id="grid1" ui-grid="gridData" class="grid" ui-grid-auto-resize style="height: {{gridHeight}}"></div>

Wenn angular den Stil anwendet, muss er nur in der Variablen $ scope.gridHeight nachsehen und darf keine vollständige Funktion auswerten.

3) Wenn Sie die Höhe eines erweiterbaren Gitters dynamisch berechnen möchten, ist dies komplizierter. In diesem Fall können Sie die Eigenschaft expandableRowHeight festlegen. Dadurch wird die reservierte Höhe für jedes Teilgitter festgelegt.

    $scope.gridData = {
        enableSorting: true,
        multiSelect: false,  
        enableRowSelection: true,
        showFooter: false,
        enableFiltering: true,    
        enableSelectAll: false,
        enableRowHeaderSelection: false, 
        enableGridMenu: true,
        noUnselect: true,
        expandableRowTemplate: 'subGrid.html',
        expandableRowHeight: 380,   // 10 rows * 30px + 40px (header) + 40px (filters)
        onRegisterApi: function(gridApi) {

            gridApi.expandable.on.rowExpandedStateChanged($scope, function(row){
                var height = parseInt(uiGridService.removeUnit($scope.jdeNewUserConflictsGridHeight,'px'));
                var changedRowHeight = parseInt(uiGridService.getGridHeight(row.entity.subGridNewUserConflictsGrid, true));

                if (row.isExpanded)
                {
                    height += changedRowHeight;                    
                }
                else
                {
                    height -= changedRowHeight;                    
                }

                $scope.jdeNewUserConflictsGridHeight = height + 'px';
            });
        },
        columnDefs :  [
                { field: 'GridField1', name: 'GridField1', enableFiltering: true }
        ]
    }
1
Aquiles

Ich komme zu spät zum Spiel, habe aber eine gute Lösung gefunden. Ich habe eine benutzerdefinierte Attribut-Direktive erstellt. Alles, was Sie tun müssen, ist das gridApi zu übergeben, und es berechnet automatisch die Höhe. Außerdem wird das Paginierungsänderungsereignis abonniert. Wenn der Benutzer die Seitengröße ändert, wird die Größe geändert.

class UIGridAutoResize implements ng.IDirective {
    link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes) => void;
    scope: { gridApi: "=" };
    restrict = "A";

    private previousValue: string;
    private isValid: boolean = true;
    private watch: any;

    constructor($timeout: ng.ITimeoutService) {
        UIGridAutoResize.prototype.link = (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes) => {
            const gridOptions = scope.$eval(attrs.uiGrid) as any;
            const gridApi = scope.$eval(attrs.gridResize) as any;

            gridApi.core.on.rowsRendered(scope, () => {
                $timeout(() => {
                    this.autoSizeGrid(element, attrs, gridOptions, gridApi, false);
                }, 100);
            });

            gridApi.core.on.filterChanged(scope, () => {
                this.autoSizeGrid(element, attrs, gridOptions, gridApi, false);
            });

            if (attrs.uiGridPagination === "") {
                gridApi.pagination.on.paginationChanged(null, () => {
                    this.autoSizeGrid(element, attrs, gridOptions, gridApi, true);
                });
            }

            angular.element(window).resize(() => {
                $timeout(() => {
                    this.autoSizeGrid(element, attrs, gridOptions, gridApi, false);
                }, 100);
            });
        };
    }

    static Factory(): ng.IDirectiveFactory {
        const directive = ($timeout: ng.ITimeoutService) => {
            return new UIGridAutoResize($timeout);
        };

        directive["$inject"] = ["$timeout"];

        return directive;
    }

    private autoSizeGrid(element: ng.IAugmentedJQuery, attrs: ng.IAttributes, gridOptions: any, gridApi: any, isPaginationChanged: boolean) {
        gridApi.core.handleWindowResize();

        // Clear empty grid message 
        angular.element(element.parent()).find("#emptyGridMessage").remove();
        element.find(".ui-grid-viewport").css("display", "");

        if (attrs.hidePageSize === "") {
            element.find(".ui-grid-pager-row-count-picker").css("display", "none");
        }

        let rowCount = gridApi.core.getVisibleRows().length;

        const headerElements = element.find(".ui-grid-header");
        let headerHeight = 2;

        if (headerElements.length > 1) { // If we have more than one header element the grid is using grouping
            const headerElement = angular.element(headerElements[1]);
            headerHeight += headerElement.height();
        } else {
            headerHeight += headerElements.height();
        }

        if (attrs.uiGridPagination === "") {
            if (rowCount < 1) {
                gridOptions.enablePagination = false;
                gridOptions.enablePaginationControls = false;
                element.css("height", (rowCount * 30) + headerHeight - 2);
                element.find(".ui-grid-viewport").css("display", "none");
                angular.element("<div id='emptyGridMessage' style='font-size: 1em; width: 100%; background-color: white; border: 1px solid #d4d4d4; padding: 7px 12px; color: #707070;'><span style='opacity: 0.95;'>There are no records.</span></div>").insertAfter(element);
            } else if (gridApi.core.getVisibleRows().length < gridOptions.paginationPageSize && !isPaginationChanged) {
                gridOptions.enablePagination = false;
                gridOptions.enablePaginationControls = false;
                element.css("height", (rowCount * 30) + headerHeight);
            } else {
                gridOptions.enablePagination = true;
                gridOptions.enablePaginationControls = true;              
                element.css("height", (rowCount * 30) + headerHeight);
            }
        } else {
            if (rowCount < 1) {
                element.css("height", (rowCount * 30) + headerHeight - 2);
                element.find(".ui-grid-viewport").css("display", "none");
                angular.element("<div id='emptyGridMessage' style='font-size: 1em; width: 100%; background-color: white; border: 1px solid #d4d4d4; padding: 7px 12px; color: #707070;'><span style='opacity: 0.95;'>There are no records.</span></div>").insertAfter(element);
            } else {
                element.css("height", (rowCount * 30) + headerHeight);
            }
        }

        // Add extra margin to prevent scroll bar and pager from overlapping content underneath
        const pagerHeight = element.find(".ui-grid-pager-panel").height();

        if (rowCount > 0) {
            if (pagerHeight > 0)
                element.css("margin-bottom", pagerHeight);
            else
                element.css("margin-bottom", 10);
        } else {
            if (pagerHeight > 0)
                angular.element(element.parent()).find("#emptyGridMessage").css("margin-bottom", pagerHeight);
            else 
                angular.element(element.parent()).find("#emptyGridMessage").css("margin-bottom", 10);
        }

        if (rowCount > gridOptions.paginationPageSize) // Sometimes paging shows all rows this fixes that
           gridApi.core.refresh();
    }
}
<div ui-grid="vm.gridOptions" grid-resize="vm.gridApi" ui-grid-resize-columns ui-grid-pagination></div>
1
Jamie Steele

änderte die Funktion getTableHeight () nach dem @ tony-Ansatz in

<div id="grid1" ui-grid="$ctrl.gridOptions" class="grid" ui-grid-auto-resize style="{{$ctrl.getTableHeight()}}"></div>

getTableHeight() {
    var offsetValue = 365;
    return "height: " + parseInt(window.innerHeight - offsetValue ) + "px!important";
}

das Gitter würde auch in Bezug auf die Fensterhöhe eine dynamische Höhe haben.

0
cmTanko

tonys Ansatz funktioniert für mich, aber wenn man ein console.log erstellt, wird die Funktion getTableHeight zu oft aufgerufen (sortieren, Menü klicken ...)

Ich ändere es so, dass die Höhe nur neu berechnet wird, wenn ich Zeilen hinzufüge/entferne. Anmerkung: tableData ist das Array von Zeilen

$scope.getTableHeight = function() {
   var rowHeight = 30; // your row height
   var headerHeight = 30; // your header height
   return {
      height: ($scope.gridData.data.length * rowHeight + headerHeight) + "px"
   };
};

$scope.$watchCollection('tableData', function (newValue, oldValue) {
    angular.element(element[0].querySelector('.grid')).css($scope.getTableHeight());
});

HTML

<div id="grid1" ui-grid="gridData" class="grid" ui-grid-auto-resize"></div>
0
dephiros