Why does ui-grid pagination look so crooked? - angularjs

This is my current code:
var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.pagination']);
app.controller('MainCtrl', [
'$scope', '$http', 'uiGridConstants', function($scope, $http, uiGridConstants) {
var paginationOptions = {
pageNumber: 1,
pageSize: 25,
sort: null
};
$scope.gridOptions = {
paginationPageSizes: [25, 50, 75],
paginationPageSize: 25,
useExternalPagination: true,
useExternalSorting: true,
columnDefs: [
{ name: 'name' },
{ name: 'gender', enableSorting: false },
{ name: 'company', enableSorting: false }
],
onRegisterApi: function(gridApi) {
$scope.gridApi = gridApi;
$scope.gridApi.core.on.sortChanged($scope, function(grid, sortColumns) {
if (sortColumns.length == 0) {
paginationOptions.sort = null;
} else {
paginationOptions.sort = sortColumns[0].sort.direction;
}
getPage();
});
gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) {
paginationOptions.pageNumber = newPage;
paginationOptions.pageSize = pageSize;
getPage();
});
}
};
var getPage = function() {
var url;
switch(paginationOptions.sort) {
case uiGridConstants.ASC:
url = 'https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100_ASC.json';
break;
case uiGridConstants.DESC:
url = 'https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100_DESC.json';
break;
default:
url = 'https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100.json';
break;
}
$http.get(url)
.success(function (data) {
$scope.gridOptions.totalItems = 100;
var firstRow = (paginationOptions.pageNumber - 1) * paginationOptions.pageSize;
$scope.gridOptions.data = data.slice(firstRow, firstRow + paginationOptions.pageSize);
});
};
getPage();
}
]);
.grid {
width: 600px;
}
<!doctype html>
<html ng-app="app">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular-touch.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular-animate.js"></script>
<script src="http://ui-grid.info/release/ui-grid.js"></script>
<link rel="stylesheet" href="http://ui-grid.info/release/ui-grid.css" type="text/css">
<link rel="stylesheet" href="main.css" type="text/css">
</head>
<body>
<div ng-controller="MainCtrl">
<div ui-grid="gridOptions" ui-grid-pagination class="grid"></div>
</div>
<script src="app.js"></script>
</body>
</html>
Here is the original plunker link as a reference: http://plnkr.co/edit/unizPGE4JCFxr5e5jQut?p=preview
The result I am getting is displayed in the following image. As you can see the pagination area seems to be "broken", with wrong sizing and alignments.
Why is the pagination so crookedly? What can I do with this?

Well, let me get started.
First, you are using angular 1.2.26 with the release version of ui-grid. While this doesn't seem to trigger any rendering problem, the official page for UI-Grid advertises a compatibility for Angularjs version 1.4.x to 1.6.x. If you open the developer toolbar you can actually see there is a reported error just because of that.
($scope.$applyAsync was added to Angularjs starting on version 1.3.x. Related info here)
I advise you upgrade to a compatible angularjs version to avoid further problem. Since you are also using the $http.success() construct, which was dropped after angularjs 1.4.3 your best bet is to stick to that version.
As for the pager rendering problem, it would seem that the wrong alignment is caused by the page number input box getting a wrong size. I compared your sample with the one on the official UI-Grid homepage and noticed that in your case the input seems to be missing a box-sizing: border-box setting. Because of this the specified height: 26px; attribute won't include the item padding: so, while on the UI-Grid sample the input will be 26 px high including the 5px padding, in your plunker the padding are added to the height, resulting in a 26+5+5 px high input that is obviously higher than any other element on the line.
Based on my observation, the border-box setting on the original sample is coming from bootstrap-flatly.min.css. I didn't find any notice of bootstrap begin an explicit requirement for paging support, but I don't exclude it. Anyway, in your specific case, adding the missing attribute on the input should be enough.
var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.pagination']);
app.controller('MainCtrl', [
'$scope', '$http', 'uiGridConstants', function($scope, $http, uiGridConstants) {
var paginationOptions = {
pageNumber: 1,
pageSize: 25,
sort: null
};
$scope.gridOptions = {
paginationPageSizes: [25, 50, 75],
paginationPageSize: 25,
useExternalPagination: true,
useExternalSorting: true,
columnDefs: [
{ name: 'name' },
{ name: 'gender', enableSorting: false },
{ name: 'company', enableSorting: false }
],
onRegisterApi: function(gridApi) {
$scope.gridApi = gridApi;
$scope.gridApi.core.on.sortChanged($scope, function(grid, sortColumns) {
if (sortColumns.length == 0) {
paginationOptions.sort = null;
} else {
paginationOptions.sort = sortColumns[0].sort.direction;
}
getPage();
});
gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) {
paginationOptions.pageNumber = newPage;
paginationOptions.pageSize = pageSize;
getPage();
});
}
};
var getPage = function() {
var url;
switch(paginationOptions.sort) {
case uiGridConstants.ASC:
url = 'https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100_ASC.json';
break;
case uiGridConstants.DESC:
url = 'https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100_DESC.json';
break;
default:
url = 'https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100.json';
break;
}
$http.get(url)
.success(function (data) {
$scope.gridOptions.totalItems = 100;
var firstRow = (paginationOptions.pageNumber - 1) * paginationOptions.pageSize;
$scope.gridOptions.data = data.slice(firstRow, firstRow + paginationOptions.pageSize);
});
};
getPage();
}
]);
.grid {
width: 600px;
}
.ui-grid-pager-control-input{
box-sizing: border-box !important;
}
<!doctype html>
<html ng-app="app">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-touch.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-animate.js"></script>
<script src="http://ui-grid.info/release/ui-grid.js"></script>
<link rel="stylesheet" href="http://ui-grid.info/release/ui-grid.css" type="text/css">
<link rel="stylesheet" href="main.css" type="text/css">
</head>
<body>
<div ng-controller="MainCtrl">
<div ui-grid="gridOptions" ui-grid-pagination class="grid"></div>
</div>
<script src="app.js"></script>
</body>
</html>
As you can see in the above sample, I switched the referenced angularjs file version to 1.4.3 and I added the following css rule:
.ui-grid-pager-control-input{
box-sizing: border-box !important;
}
This is the result:
still not very nice, but it seems to be identical to the result I am seeing on the official site:
As a final notice, please consider that the pagination api currently seems to be still in early alpha stage (see: http://ui-grid.info/docs/#!/tutorial/214_pagination), so it may not yet fit your need or present mayor bugs.

If you don't need this pagination controls, you can hide this by add enablePaginationControls false in gridOptions.
And can use other components like 'uib-pagination' for external pagination.

Related

Use 2 ui-codemirrors in 1 controller

I am coding a very very basic playground by using AngularJS and ui-codemirror. Here is the code (JSBin).
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui/0.4.0/angular-ui.css">
<link rel="stylesheet" href="https://codemirror.net/lib/codemirror.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
<script src="https://codemirror.net/lib/codemirror.js"></script>
<script src="https://codemirror.net/addon/edit/matchbrackets.js"></script>
<script src="https://codemirror.net/mode/htmlmixed/htmlmixed.js"></script>
<script src="https://codemirror.net/mode/xml/xml.js"></script>
<script src="https://codemirror.net/mode/javascript/javascript.js"></script>
<script src="https://codemirror.net/mode/css/css.js"></script>
<script src="https://codemirror.net/mode/clike/clike.js"></script>
<script src="https://codemirror.net/mode/php/php.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui/0.4.0/angular-ui.js"></script>
</head>
<body>
<div ng-app="myApp">
<div ng-controller="codeCtrl">
HTML:<br>
<textarea ui-codemirror ng-model="html"></textarea>
<br>CSS:<br>
<textarea ui-codemirror ng-model="css"></textarea>
</div>
Output:
<section id="output">
<iframe></iframe>
</section>
</div>
</body>
</html>
JavaScript:
var myApp = angular.module('myApp', ['ui']);
myApp.value('ui.config', {
codemirror: {
mode: 'text/x-php',
lineNumbers: true,
matchBrackets: true,
}
});
function codeCtrl($scope, codeService) {
$scope.html = '<body>default</body>';
$scope.css = "body {color: red}";
$scope.$watch('html', function () { codeService.render($scope.html, $scope.css); }, true);
$scope.$watch('css', function () { codeService.render($scope.html, $scope.css); }, true);
}
myApp.service('codeService', function () {
this.render = function (html, css) {
source = "<html><head><style>" + css + "</style></head>" + html +"</html>";
var iframe = document.querySelector('#output iframe'),
iframe_doc = iframe.contentDocument;
iframe_doc.open();
iframe_doc.write(source);
iframe_doc.close();
}
})
The above code works, but the problem is it applies one same ui.config to 2 ui-codemirror. Does anyone know how to apply mode html to the first ui-codemirror and mode css to the second ui-codemirror?
Additionally, how could I set the height (or rows) and width (or cols) of a ui-codemirror?
Since you're dealing with two separate text areas that have rather different roles (or imagine if they were more), it makes sense to define separate directives for them, each one accepting a different config object. I've created a JSBin which shows one possible approach, via directive factory that can be used to generated different "mirrors".
angular.module('codeMirrorApp')
.factory('CodeMirrorFactory', ['$parse',
function($parse) {
return {
createDirective: function(config) {
var configString = JSON.stringify(config);
return {
scope: true,
restrict: 'E',
template: '<textarea ui-codemirror=' + configString + ' ng-model="content"></textarea>',
controller: ['$scope', '$attrs', function($scope, $attrs) {
var handler = $parse($attrs.handler);
$scope.$watch('content', function(value) {
handler($scope, { content: value });
});
}]
};
}
};
}
]);
I'm intentionally using handlers provided by the parent controller instead of bindings to the parent scope as this makes things look more understandable even while looking at the HTML markup.
The controller:
angular.module('codeMirrorApp')
.controller('MirrorsController', ['RenderMirrors',
function(RenderMirrors) {
var ctrl = this,
html,
css;
ctrl.handleHtml = function(htmlString) {
html = htmlString;
RenderMirrors.render(html, css);
};
ctrl.handleCss = function(cssString) {
css = cssString;
RenderMirrors.render(html, css);
};
}
]);
Markup:
<div ng-app="codeMirrorApp">
<div ng-controller="MirrorsController as ctrl">
HTML:<br>
<html-code-mirror handler="ctrl.handleHtml(content)"></html-code-mirror>
<br>CSS:<br>
<css-code-mirror handler="ctrl.handleCss(content)"></css-code-mirror>
</div>
Output:
<section id="output">
<iframe></iframe>
</section>
</div>
Hope this helps.
Controller:
function codeCtrl($scope, codeService) {
$scope.editorOptions1 = {mode: 'text/html',
lineNumbers: false,
matchBrackets: true};
$scope.editorOptions2 = {mode: 'text/css',
lineNumbers: true,
matchBrackets: true};
$scope.html = '<body>default</body>';
$scope.css = "body {color: red}";
$scope.$watch('html', function () { codeService.render($scope.html, $scope.css); }, true);
$scope.$watch('css', function () { codeService.render($scope.html, $scope.css); }, true);
}
Html :
<div ng-controller="codeCtrl">
HTML:<br>
<textarea ui-codemirror="editorOptions1" ng-model="html"></textarea>
<br>CSS:<br>
<textarea ui-codemirror="editorOptions2" ng-model="css"></textarea>
</div>

Angular ui-grid use selectedrow feature to control content of a row column

I would like to the ui-grid row select feature to set the value of a column in the clicked row.
I have a column in the DB named omit. I would like that value to equal the state of the selected row, so if the row is selected then omit = 1, if row is not selected then omit = 0. I think I have this part figured out (however I'm always open to better ideas!).
gridApi.selection.on.rowSelectionChanged($scope,function(row){
if(row.isSelected){
row.entity.omit = 1;
}
if(!row.isSelected){
row.entity.omit = 0;
}
// now save to database...
});
gridApi.selection.on.rowSelectionChangedBatch($scope,function(rows){
angular.forEach(rows, function(value, key) {
if(value.isSelected){
value.entity.omit = 1;
}
if(!value.isSelected){
value.entity.omit = 0;
}
// now save to database...
});
});
What I haven't been able to figure out is how the select the row when the grid is first loaded.
So, on the initial load of the grid, how do I select the row if the value of omit is 1?
You can use the gridApi.selection.selectRow method, but you have to wait until the grid has digested the data for it to work. So you either have to set it on an $interval (or after a $timeout) to keep running while the grid digests the data, or you can call gridApi.grid.modifyRows($scope.gridOptions.data) before you call selectRow... to be honest, I'm not sure why you have to call that.
var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.selection']);
app.controller('gridCtrl', ['$scope', '$http', '$interval', 'uiGridConstants', function ($scope, $http, $interval, uiGridConstants) {
$scope.gridOptions = { enableRowSelection: true, enableRowHeaderSelection: false };
$scope.gridOptions.columnDefs = [
{ name: 'omit' },
{ name: 'id' },
{ name: 'name'},
{ name: 'age', displayName: 'Age (not focusable)', allowCellFocus : false },
{ name: 'address.city' }
];
$scope.gridOptions.multiSelect = false;
$scope.gridOptions.modifierKeysToMultiSelect = false;
$scope.gridOptions.noUnselect = true;
$scope.gridOptions.onRegisterApi = function( gridApi ) {
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope,function(row){
if(row.isSelected){
row.entity.omit = 1;
}
if(!row.isSelected){
row.entity.omit = 0;
}
// now save to database...
});
gridApi.selection.on.rowSelectionChangedBatch($scope,function(rows){
angular.forEach(rows, function(value, key) {
if(value.isSelected){
value.entity.omit = 1;
}
if(!value.isSelected){
value.entity.omit = 0;
}
// now save to database...
});
});
};
$scope.toggleRowSelection = function() {
$scope.gridApi.selection.clearSelectedRows();
$scope.gridOptions.enableRowSelection = !$scope.gridOptions.enableRowSelection;
$scope.gridApi.core.notifyDataChange( uiGridConstants.dataChange.OPTIONS);
};
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json')
.success(function(data) {
_.forEach(data, function(row) {
row.omit = 0;
});
/* arbitrarily setting the fourth row's omit value to 1*/
data[3].omit = 1;
$scope.gridOptions.data = data;
/* using lodash find method to grab the row with omit === 1 */
/* could also use native JS filter, which returns array rather than object */
var initSelected = _.find($scope.gridOptions.data, function(row) { return row.omit === 1; });
$scope.gridApi.grid.modifyRows($scope.gridOptions.data);
$scope.gridApi.selection.selectRow(initSelected);
/**
* OR:
* $interval( function() {
* $scope.gridApi.selection.selectRow(initSelected);
* }, 0, 1);
*/
});
}]);
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="lodash.js#4.6.1" data-semver="4.6.1" src="https://cdn.jsdelivr.net/lodash/4.6.1/lodash.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-touch.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-animate.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/csv.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/pdfmake.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/vfs_fonts.js"></script>
<script src="http://ui-grid.info/release/ui-grid.js"></script>
<link rel="stylesheet" href="http://ui-grid.info/release/ui-grid.css" type="text/css" />
<link rel="stylesheet" href="main.css" type="text/css" />
</head>
<body>
<div ng-controller="gridCtrl">
<div ui-grid="gridOptions" ui-grid-selection="" class="grid"></div>
</div>
</body>
</html>

How can I load multiple ace editor sessions without multiple worker requests

I have the following code which basically loads three JavaScript ace editor sessions:
But the problem is for each and every session it creates new worker-javascript.js network request for the same mode. I am supposed to have editor for 10 to 30 JavaScript ace-editor sessions in the single page to write different functions in JavaScript at various places, so this is eating memory and getting my Chrome browser crashed as it is requesting the worker every time for the same mode.
Following is my sample html file: (With angular app)
<!DOCTYPE <!DOCTYPE html>
<html ng-app="editorApp">
<head>
<title>Ace editor tst</title>
<script type="text/javascript" src="bower_components/angular/angular.js"></script>
<script type="text/javascript" src="bower_components/ace-builds/src/ace.js"></script>
<script type="text/javascript" src="bower_components/angular-ui-ace/ui-ace.js"></script>
<script type="text/javascript" src="bower_components/ace-builds/src/ext-language_tools.js"></script>
<script type="text/javascript" src="index.js"></script>
<style type="text/css">
.e1 { height: 200px; margin-bottom: 5px;}
.e2 { height: 200px; margin-bottom: 5px;}
.e3 { height: 200px; margin-bottom: 5px;}
</style>
</head>
<body ng-controller="appCtrl">
<div class="e1" ui-ace="{
workerPath: 'bower_components/ace-builds/src-min-noconflict/',
useWrapMode : true,
showGutter: true,
theme:'twilight',
firstLineNumber: 1,
onLoad: aceLoaded,
onChange: aceChanged,
require: ['ace/ext/language_tools'],
advanced: {
enableSnippets: true,
enableBasicAutocompletion: true,
enableLiveAutocompletion: true
}
}"></div>
<div class="e2" ui-ace="{
workerPath: 'bower_components/ace-builds/src-min-noconflict/',
useWrapMode : true,
showGutter: true,
theme:'twilight',
firstLineNumber: 1,
onLoad: aceLoaded,
onChange: aceChanged,
require: ['ace/ext/language_tools'],
advanced: {
enableSnippets: true,
enableBasicAutocompletion: true,
enableLiveAutocompletion: true
}
}"></div>
<div class="e3" ui-ace="{
workerPath: 'bower_components/ace-builds/src-min-noconflict/',
useWrapMode : true,
showGutter: true,
theme:'twilight',
firstLineNumber: 1,
onLoad: aceLoaded,
onChange: aceChanged,
require: ['ace/ext/language_tools'],
advanced: {
enableSnippets: true,
enableBasicAutocompletion: true,
enableLiveAutocompletion: true
}
}"></div>
</body>
</html>
Following is my controller: (index.js)
var app = angular.module('editorApp', ['ui.ace']);
app.controller('appCtrl', function($scope){
$scope.aceLoaded = function(_editor){
var _session = _editor.getSession();
_session.setMode('ace/mode/javascript');
var _renderer = _editor.renderer;
_editor.$blockScrolling = Infinity;
}
/* $scope.acesession = "";
$scope.aceLoaded = function(_editor){
var _session = "";
if(!$scope.acesession) {
_session = _editor.getSession();
_session.setMode('ace/mode/javascript');
$scope.acesession = _session;
}
else {
_session = $scope.acesession;
}
var _renderer = _editor.renderer;
_editor.$blockScrolling = Infinity;
}*/
});
I have even tried by using the same session (commented code above) as discussed at https://github.com/ajaxorg/ace/issues/344 , but didn't work.
Any help would be appreciated.
Plnkr is here http://plnkr.co/edit/lJUAW9EXsiC7RVuga9ia
Try this.
Update the editor session to use the the worker only for the active ace editor.
_editor.on('focus', function () {
_editor.getSession().setUseWorker(true);
});
_editor.on('blur', function () {
_editor.getSession().setUseWorker(false);
});
var _session = _editor.getSession();
_session.setUseWorker(false);
_session.setMode('ace/mode/javascript');
var _renderer = _editor.renderer;
_editor.$blockScrolling = Infinity;
Working Plnkr: http://plnkr.co/edit/B1fuFguofn8cwiUEFnyp?p=preview

How to display Ui-grid after data getting from services?

This is my code
var app = angular.module('app', ['ngTouch', 'ui.grid']);
app.controller('MainCtrl', ['$scope', '$http', function ($scope, $http) {
var today = new Date();
$scope.gridOptions = {
enableFiltering: false,
onRegisterApi: function(gridApi){
$scope.gridApi = gridApi;
$scope.gridApi.grid.registerRowsProcessor( $scope.singleFilter, 200 );
},
columnDefs: [
{ field: 'name' },
{ field: 'gender', cellFilter: 'mapGender' },
{ field: 'company' },
{ field: 'email' },
{ field: 'phone' },
{ field: 'age' },
{ field: 'mixedDate' }
]
};
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json')
.success(function(data) {
$scope.gridOptions.data = data;
$scope.gridOptions.data[0].age = -5;
data.forEach( function addDates( row, index ){
row.mixedDate = new Date();
row.mixedDate.setDate(today.getDate() + ( index % 14 ) );
row.gender = row.gender==='male' ? '1' : '2';
});
});
$scope.filter = function() {
$scope.gridApi.grid.refresh();
};
$scope.singleFilter = function( renderableRows ){
var matcher = new RegExp($scope.filterValue);
renderableRows.forEach( function( row ) {
var match = false;
[ 'name', 'company', 'email' ].forEach(function( field ){
if ( row.entity[field].match(matcher) ){
match = true;
}
});
if ( !match ){
row.visible = false;
}
});
return renderableRows;
};
}])
.filter('mapGender', function() {
var genderHash = {
1: 'male',
2: 'female'
};
return function(input) {
if (!input){
return '';
} else {
return genderHash[input];
}
};
});
<!doctype html>
<html ng-app="app">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-touch.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-animate.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/csv.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/pdfmake.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/vfs_fonts.js"></script>
<script src="http://ui-grid.info/release/ui-grid.js"></script>
<link rel="stylesheet" href="http://ui-grid.info/release/ui-grid.css" type="text/css">
<link rel="stylesheet" href="main.css" type="text/css">
</head>
<body>
<div ng-controller="MainCtrl">
<input ng-model='filterValue'/><button ng-click='filter()'>Filter</button>
<div id="grid1" ui-grid="gridOptions" class="grid"></div>
</div>
<script src="app.js"></script>
</body>
</html>
In the above code first ui-grid structure display then after data will bind to the ui-grid, but i want to display entire grid with structure after loading data.
this is my plunker http://plnkr.co/edit/?p=preview
A popular design is to show loading status when data is not yet loaded, to do so, you could add a dataLoaded flag to control when the grid is ready, set the flag as true in the success callback of $http.get. See the below:
$scope.dataLoaded = false;
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json').success(function(data) {
// ...
$scope.dataLoaded = true;
});
and in your template, it could be as:
<div id="grid1" ui-grid="gridOptions" class="grid" ng-show="dataLoaded"></div>
<div ng-hide="dataLoaded">Loading...</div>

ng-grid Auto / Dynamic Height

How do I get ng-grid to auto resize its height based on the page size? The documentation on ng-grid's site uses a fixed height. The best solution I've seen comes from this link:
.ngViewport.ng-scope {
height: auto !important;
overflow-y: hidden;
}
.ngTopPanel.ng-scope, .ngHeaderContainer {
width: auto !important;
}
This does not work with server-side paging. I've copied the server-side paging example from ng-grid's site, and applied the css above, but as you can see, only the first 6 rows are shown: http://plnkr.co/edit/d9t5JvebRjUxZoHNqD7K?p=preview
And { height: 100% } does not work...
You can try using the ng-grid Flexible Height Plugin, all you need to do is add this plugin to the plugins property in grid options and he'll take care of the rest .
Example:
$scope.gridOptions = {
data: 'myData',
enablePaging: true,
showFooter: true,
totalServerItems: 'totalServerItems',
pagingOptions: $scope.pagingOptions,
filterOptions: $scope.filterOptions,
plugins: [new ngGridFlexibleHeightPlugin()]
};
Live example: http://plnkr.co/edit/zNHhsEVqmpQmFWrJV1KQ?p=preview
If you don't want to add any plugins I've implemented an easy solution to dynamically change the table's height strictly based on the visible rows. I am using Ui-Grid-Unstable v3.0. No need to touch CSS.
My HTML looks like:
<div id="grid1" ui-grid="gridOptions" ui-grid-grouping ui-grid-exporter class="grid"></div>
In your controller add:
$scope.$watch('gridApi.core.getVisibleRows().length', function() {
if ($scope.gridApi) {
$scope.gridApi.core.refresh();
var row_height = 30;
var header_height = 31;
var height = row_height * $scope.gridApi.core.getVisibleRows().length + header_height;
$('.grid').height(height);
$scope.gridApi.grid.handleWindowResize();
}
});
And to turn off scrolling add the following line where gridOptions is initialized:
enableVerticalScrollbar : uiGridConstants.scrollbars.NEVER,
Make sure uiGridConstants is passed into your controller:
angular.module('app').controller('mainController', function($scope, uiGridConstants) { ...
Hope this helps!
I think I solved this problem perfectly after 48 hours,
var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.pagination', 'ui.grid.autoResize']);
app.controller('MainCtrl', ['$scope', '$http', '$interval', function($scope, $http, $interval) {
var paginationOptions = {
pageNumber: 1,
pageSize: 20,
};
$scope.currentPage = 1;
$scope.pageSize = paginationOptions.pageSize;
$scope.gridOptions = {
rowHeight: 30,
enableSorting: true,
paginationPageSizes: [$scope.pageSize, $scope.pageSize * 2, $scope.pageSize * 3],
paginationPageSize: paginationOptions.pageSize,
columnDefs: [{
name: 'name'
}, {
name: 'gender',
enableSorting: false
}, {
name: 'company',
enableSorting: false
}],
onRegisterApi: function(gridApi) {
$scope.gridApi = gridApi;
gridApi.pagination.on.paginationChanged($scope, function(newPage, pageSize) {
paginationOptions.pageNumber = newPage;
paginationOptions.pageSize = pageSize;
$scope.pageSize = pageSize;
$scope.currentPage = newPage;
$scope.totalPage = Math.ceil($scope.gridOptions.totalItems / $scope.pageSize);
});
}
};
var loadData = function() {
var url = 'https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100.json';
$http.get(url)
.success(function(data) {
$scope.gridOptions.totalItems = data.length;
$scope.totalPage = Math.ceil($scope.gridOptions.totalItems / $scope.pageSize);
$scope.gridOptions.data = data;
});
};
loadData();
// for resize grid's height
$scope.tableHeight = 'height: 600px';
function getTableHeight(totalPage, currentPage, pageSize, dataLen) {
var rowHeight = 30; // row height
var headerHeight = 50; // header height
var footerHeight = 60; // bottom scroll bar height
var totalH = 0;
if (totalPage > 1) {
// console.log('hehehehe');
if (currentPage < totalPage) {
totalH = pageSize * rowHeight + headerHeight + footerHeight;
} else {
var lastPageSize = dataLen % pageSize;
// console.log(lastPageSize);
if (lastPageSize === 0) {
totalH = pageSize * rowHeight + headerHeight + footerHeight;
} else {
totalH = lastPageSize * rowHeight + headerHeight + footerHeight;
}
}
console.log(totalH);
} else {
totalH = dataLen * rowHeight + headerHeight + footerHeight;
}
return 'height: ' + (totalH) + 'px';
}
$interval(function() {
$scope.tableHeight = getTableHeight($scope.totalPage,
$scope.currentPage, $scope.pageSize,
$scope.gridOptions.data.length);
console.log($scope.tableHeight);
$scope.gridApi.grid.handleWindowResize();
$scope.gridApi.core.refresh();
}, 200);
}]);
.grid {
width: 600px;
}
<!doctype html>
<html ng-app="app">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-touch.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-animate.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/csv.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/pdfmake.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/vfs_fonts.js"></script>
<script src="http://ui-grid.info/release/ui-grid.js"></script>
<link rel="stylesheet" href="http://ui-grid.info/release/ui-grid.css" type="text/css">
<link rel="stylesheet" href="main.css" type="text/css">
</head>
<body>
<div ng-controller="MainCtrl">
<div ui-grid="gridOptions" ui-grid-pagination id="grid" style="{{tableHeight}}"></div>
<div>
<p>Current Page: {{ currentPage }}</p>
<p>Total Page: {{ totalPage }}</p>
<p>Page Size: {{ pageSize }}</p>
<p>Table Height: {{tableHeight}}</p>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
Also see Plunker: http://plnkr.co/edit/np6y6rgN1ThnT0ZqyJeo?p=preview
$(".gridStyle").css("height","");
remove your height property in your gridstyle class then automatic dynamic height set on your ng-grid..
you can add auto style something like this:
ng-style="{ 'height': myData.length*34 }",and myData is
I find using this piece of code on the stylesheet solved my problem. I disabled the plugin but it works either way.
.ngViewport.ng-scope{
height: auto !important;
overflow-y: hidden;
}
.ngTopPanel.ng-scope, .ngHeaderContainer{
width: auto !important;
}
.ngGrid{
background-color: transparent!important;
}
I hope it helps someone!
In the method where you are trying to store the data for each row within each grid, add a code to calculate the length of the grid in a separate array and push that calculated length to different array. Make sure the index of the grid and index of the array should be same, so that we can access it from the UI together. My approach was as follows:
//Stores the calculated height of each grid.
$scope.gridHeights = [];
//Returns the height of the grid based on the 'id' passed from the UI side.
//Returns the calculated height appended with 'px' to the HTML/UI
$scope.getHeight = function(id){
if($scope.gridHeights[id]) {
return {
'height': $scope.gridHeights[id] + 'px'
};
}else{
return {
'height': '300px'
};
}
};
for (var idx = 0; idx < $scope.auditData.length; idx++) {
//gets the rows for which audit trail/s has to be displayed based on single or multi order.
$scope.gridData[idx] = $scope.auditData[idx].omorderAuditTrailItems;
//Calculates and pushes the height for each grid in Audit Trail tab.
$scope.gridHeights.push(($scope.auditData[idx].omorderAuditTrailItems.length + 2)*30);
//IN HTML, set the height of grid as :
<div id='orderAuditTrailList'>
<div class="row fits-auditTrail" ng-style="getHeight(id)">
<div class="fits-ng-grid" ng-if="auditTrail.omorderAuditTrailItems.length>0" ng-grid="gridOrderAuditTrailList[id]" ng-style="getHeight(id)"></div>
</div>
</div>

Resources