how to apply sorting in ui-grid? - angularjs

I have one angularjs project in which I am using ui-grid.
As you can see in my code, I have some attribute in cell-template. I have to perform sorting based on "rating-percentage".
So I am trying to write a sorting algorithm which required row.entity property.
My question is that how can I add rating percentage in row.entity.
What is the right way to perform sorting using "rating-percentage"?
Below is my code:
define([
'angular'
], function (angular) {
function SelectToolController($scope, $timeout, $filter) {
var vm = this,
_gridApi,
_cellTemplate,
_columnDefs,
_starRatingTemplate,
_starRatingColumn;
_starRatingTemplate =[
'<div class="ui-grid-cell-contents ">',
'<div class="opr-star-rating" >',
'<opr-star-rating rating-percentage="{{rowRenderIndex}}"',
'total-count="23"',
'suffix-display="true"',
'rating-display="true"',
'count-display="22">',
'</opr-star-rating>',
'</div>',
'</div>'
].join('');
_starRatingColumn = {
name: 'starRating',
cellTemplate: _starRatingTemplate,
displayName: 'Rating',
enableFiltering: false,
enableSorting: true,
cellClass: 'star-column',
enableHiding: false,
enableRowSelection: true,
}
_columnDefs.push(_starRatingColumn);
})();

You can define your custom sorting function then link this function to column definition.
$scope.sortFun=function(a, b) {
///.... your logic
}
_starRatingColumn = {
name: 'starRating',
cellTemplate: _starRatingTemplate,
displayName: 'Rating',
enableFiltering: false,
enableSorting: true,
cellClass: 'star-column',
enableHiding: false,
enableRowSelection: true,
'sortingAlgorithm': $scope.sortFun
}
change your template.
'<div class="ui-grid-cell-contents ">',
'<div class="opr-star-rating" ng-class="col.colIndex() >',
'<opr-star-rating rating-percentage="{{row.entity}}"',
'total-count="23"',
'suffix-display="true"',
'rating-display="true"',
'count-display="22">',
'</opr-star-rating>',
'</div>',
'</div>'

Related

AngularJS cell navigation not working while using with celltemplate

I am having following code in my controller:
app.controller("homeController", homeController);
homeController.$inject = ["ui.grid.cellNav", "$scope"];
$scope.gridOptions = {
enableRowSelection: true,
enableSelectAll: true,
modifierKeysToMultiSelect: false,
enableRowHeaderSelection: false,
};
vm.objectViewGridOptions = {
enableColumnMenus: false,
enableSorting: true,
enableGridMenu: true,
angularCompileRows: true,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableRowSelection: true,
enableRowHeaderSelection: false,
exporterMenuPdf: false,
onRegisterApi: function (gridApi) {
//set gridApi on scope
vm.objectViewGridOptions.gridApi = gridApi;
gridApi.cellNav.on.navigate($scope, function (newRowCol, oldRowCol){
vm.objectViewGridOptions.gridApi.selection.selectRow(newRowCol.row.entity);
vm.objectViewGridOptions.gridApi.core.notifyDataChange($scope.gridApi.grid, uiGridConstants.dataChange.COLUMN);
});
}
};
var colDef = [];
for (var i = 0; i < columnNames.length; i++) {
if (i < 4) {
colDef.push(
{
field: columnNames[i],
displayName: columnNames[i],
width: '100',
// Highlighting first row in ui-grid
cellTemplate: '<div ui-grid-selection class="ui-grid-cell-contents" ng-style="{\'background-color\':grid.appScope.getBackgroundColor(row,true)}">{{ COL_FIELD }}</div>',
sortingAlgorithm: sort
});
}
else
colDef.push(
{
field: columnNames[i],
displayName: columnNames[i],
width: '100',
cellTemplate: '<div ui-grid-selection class="ui-grid-cell-contents" ng-style="{\'background-color\':grid.appScope.getBackgroundColor(row,false)}" >{{ COL_FIELD }}</div>',
sortingAlgorithm: sort
});
}
vm.objectViewGridOptions.columnDefs = colDef;
And in my HTML:
<div style="clear:both;" ui-grid="vm.objectViewGridOptions" ng-if="vm.objectViewGridOptions.data" ui-grid-resize-columns ui-grid-cellnav ui-grid-move-columns ui-grid-exporter class="objectviewgrid"></div>
I have used cellTemplate to give background color to the grid cells and ui-grid-cellNav to navigate between the grid cells.
If I use ui-grid-cellNav along with cellTemplate, cell navigation is not working. If I comment out the cellTemplate code, then the cell navigation is working fine.
Where am I getting struck? Forget about the loop logic and all. I cannot place the entire code here. This is already looking clumsy.
I have used cellClass and cellStyle instead of cellTemplate. Here is my code in my controller:
for (var i = 0; i < columnNames.length; i++) {
if (i < 4) {
colDef.push(
{
field: columnNames[i],
displayName: columnNames[i],
width: '100',
// fix for highlighting first row in ui-grid
//cellTemplate: '<div ui-grid-selection class="ui-grid-cell-contents" ng-style="{\'background-color\':grid.appScope.getBackgroundColor(row,true)}">{{ COL_FIELD }}</div>',
cellClass: 'ui-grid-cell-contents',
cellStyle: { 'background-color': 'backgroundColor(row, true)' },
sortingAlgorithm: sort
});
}
else
colDef.push(
{
field: columnNames[i],
displayName: columnNames[i],
width: '100',
//cellTemplate: '<div ui-grid-selection class="ui-grid-cell-contents" ng-style="{\'background-color\':grid.appScope.getBackgroundColor(row,false)}" >{{ COL_FIELD }}</div>',
cellClass: 'ui-grid-cell-contents',
cellStyle: { 'background-color': 'backgroundColor(row, false)' },
sortingAlgorithm: sort
});
}
The above code allowed me to use both cellNav and cell custom style together.

Handling filter event in ui-grid

I am using angular ui-grid in my application to show data.
I have colmnDef set as follows.
$scope.grid =
data: 'userList'
enableColumnResizing: true
enableFiltering: true
enableRowSelection: true
enableRowHeaderSelection: false
enableSorting: true
minRowsToShow: 30
multiSelect: false
columnDefs: [
{
name: 'id'
field: 'id'
displayName: 'ID'
enableFiltering: false
maxWidth: 100
}
{ name: 'username', field: 'email' }
{ name: 'firstName', field: 'first_name' }
{ name: 'lastName', field: 'last_name' }
{ name: 'lastLoggedIn', field: 'last_sign_in_at', cellFilter: 'date : "medium"', enableFiltering: false }
{ name: 'locked', field: 'locked', displayName: 'Locked?', enableFiltering: false, maxWidth: 100 }
{
name: 'Impersonate',
cellTemplate: '<a class="small-button" ng-controller="AuthController" ng-click="impersonateUser({{row.entity.id}})">
<i class="fa fa-users"></i></a>',
enableFiltering: false,
enableSorting: false,
visible: $scope.hideImpersonate
}
{
name: 'Edit'
cellTemplate: '<i class="pencil-icon"></i>'
enableFiltering: false
enableSorting: false
width: 100
}
{
name: 'Delete'
cellTemplate: deleteCellTemplate1 + deleteCellTemplate2
enableFiltering: false
enableSorting: false
width: 100
}
]
onRegisterApi: (gridApi) -> $scope.gridApi = gridApi
I want to show message 'No Data Found' in the grid when user searches for a 'username' mentioned above which doesn't exist.
I tried following code, but it didn't work for me. I would like to know better approach towards this.
$scope.grid.$on('ngGridEventFilter', function(){
console.log('filter called');
});
Wow, seems like this should be a lot easier to accomplish... After a good bit of searching around, I found one way to determine the number of results is with the gridApi.grid.renderContainers.body.visibleRowCache object.
So I modified the filter example plunker on the ui-grid tutorial and incorporated a technique described in one of their github issue threads.
To accomplish it, you can transclude a conditional div into the ui-grid div, and show it when no results are found:
<div id="grid1" ui-grid="gridOptions" class="grid">
<div class="no-rows" ng-if="noFilteredResults">
<div class="msg">
<span>No Data Found</span>
</div>
</div>
</div>
In your controller you have to set a $watch on the gridApi.grid.renderContainers.body.visibleRowCache object:
$scope.noFilteredResults = false;
$scope.$watch(function() { return $scope.gridApi.grid.renderContainers.body.visibleRowCache.length; },
function(newVal, oldVal) {
if ( newVal === 0 ) {
$scope.noFilteredResults = true;
console.log('no rows!');
} else {
$scope.noFilteredResults = false;
}
});
If there's an easier way to get it done, it's not easy to find :) Hope that helps!

ng-grid Show Two Arrow Sorting Icon for Every Column Header

In ng-grid, there are two arrow icons for sorting, but it is not showing all arrows in every column header by default.
I know about setting sortInfo, but I don't want to sort when the ng-grid first initializes.
How can I show the two arrows for every column header without triggering the sorting?
--Edited--
For those requesting some code:
My gridOptions are standard.
I don't know what other code I should provide to you.
$scope.gridOptions = {
data: 'myData',
enablePaging: true,
showFooter: true,
totalServerItems: 'totalServerItems',
pagingOptions: $scope.pagingOptions,
multiSelect: false,
enableHighlighting: true,
sortInfo: { fields: [], columns: [], directions: [] },
columnDefs: [
{field: 'name', displayName: 'Company'},
{field: 'meta.orders', displayName: 'Orders'},
{field: 'meta.expenses', displayName: 'Expenses', cellFilter: 'currency: \'IDR \''},
{field: 'meta.commissions', displayName: 'Commisions', cellFilter: 'currency: \'IDR \''},
{field: 'status', displayName: 'Status'},
{field: '', cellTemplate: '<a ng-click="details(row)" class="btn btn-link" id="{{row.entity._id}}">Details</a>'}
]
};
I want to achieve something like this (see the two arrows appear) when the ng-grid is first initialized, without triggering the sort:
I've already solved it.
I got the code below from the ng-grid template docs.
var customHeaderCellTemplate = '<div ng-click="col.sort()" ng-class="{ ngSorted: !noSortVisible }">'+
'<span class="ngHeaderText">{{col.displayName}}</span>'+
'<div class="ngSortButtonDown" ng-show="showSortUp(col)"></div>'+
'<div class="ngSortButtonUp" ng-show="showSortDown(col)"></div>'+
'</div>'+
'<div ng-show="col.allowResize" class="ngHeaderGrip" ng-click="col.gripClick($event)" ng-mousedown="col.gripOnMouseDown($event)"></div>';
I modified it with my custom scope in the ng-show="showSortUp(col)" and ng-show="showSortDown(col)".
Then i put the showSortUp(col) and showSortDown(col) scope function in my controller.
The col params give us the info about the header column including sorting direction.
From the ng-grid source code, the showing arrows are controlled by sortDirection variable. In col params, we can get the sortDirection variable so we can use it to modify the original behaviour.
$scope.showSortUp = function(col) {
if(col.sortDirection == 'asc') {
return true;
} else if(col.sortDirection == 'desc') {
return false;
} else {
return true;
}
}
$scope.showSortDown = function(col) {
if(col.sortDirection == 'desc') {
return true;
} else if(col.sortDirection == 'asc') {
return false;
} else {
return true;
}
}
Also, you need to modify the .ngSortButtonUp and .ngSortButtonDown css because the original styles are broken when you show both arrows together.

UI-Bootstrap Datepicker in ng-grid not working with enableCellEditOnFocus=true

I know how to have a working UI-Bootstrap-Datepicker inside an ng-grid cell's editableCellTemplate.
My Question:
It does not work anymore when I replace the enableCellEdit=true option with enableCellEditOnFocus=true (single-click on cell to edit). Does anyone have an Idea why it breaks and how to fix that?
var editableCellTemplateUsingDatePicker = '<input ng-class="\'colt\' col.index" datepicker-popup="dd.MM.yyyy" datepicker-append-to-body=true is-open="isOpen" ng-model="COL_FIELD" my-input="COL_FIELD"/>';
$scope.gridOptions = {
data: 'myData',
//enableCellEdit: true,
enableCellEditOnFocus: true,
enableCellSelection: true,
enableRowSelection: false,
columnDefs: [{
field: 'name',
displayName: 'Name'
}, {
field:'dateOfBirth',
displayName:'Date of Birth',
editableCellTemplate: editableCellTemplateUsingDatePicker,
cellFilter: 'date:"dd.MM.yyyy"',
}]
};
Plunker
Now, I found another way to get to the desired behaviour of single-click edit with the ui-bootstrap datepicker.
You can add ng-click="editCell()" to your custom cellTemplate to enter edit-mode through single-click of the cell. Here the working setup:
var cellTemplateEditOnClick = '<div class="ngCellText" ng-click="editCell()" ng-class="col.colIndex()"><span ng-cell-text>{{row.getProperty(col.field) CUSTOM_FILTER}}</span></div>';
$scope.gridOptions = {
data: 'myData',
enableCellEdit: true,
enableCellSelection: true,
enableRowSelection: false,
columnDefs: [{
field: 'name',
displayName: 'Name',
cellTemplate: cellTemplateEditOnClick.replace('CUSTOM_FILTER', '')
}, {
field:'dateOfBirth',
displayName:'Date of Birth',
editableCellTemplate: editableCellTemplateUsingDatePicker,
cellTemplate: cellTemplateEditOnClick.replace('CUSTOM_FILTER', '| date:"dd.MM.yyyy"')
}]
};
Plunker

ng grid how to change style of individual cell in nggrid?

Just starting out with the ng-grid , how can I change the css of an individual cell in a grid.
Things like backgroundcolor but also disable and enabling of just 1 cell in the current selected row?
plunkr:http://plnkr.co/edit/zQTRd7hOR6vpVZlgfHq0?p=preview
If you define your columns with columnDefs, then you have much more flexibility. You can then add a property to the definition called cellClass that you can define in your stylesheet.
All of the column definition properties are displayed on the ng-grid wiki. If you want you can redefine the cell or header template and write custom code for anything you want.
Here is an updated plunker.
And the changed code:
$scope.gridOptions = {
data: 'myData',
selectedItems: $scope.mySelections,
enableCellEditOnFocus: true,
multiSelect: true,
afterSelectionChange: function() {
$scope.selectedIDs = [];
angular.forEach($scope.mySelections, function(item) {
$scope.selectedIDs.push(item.name)
});
},
columnDefs: [
{field:'id', displayName:'Id', cellClass: 'red'},
{field:'name', displayName:'Name', cellClass: 'blue'}
]
};
If you want you can also put a template:
$scope.gridOptions = {
data: 'myData',
selectedItems: $scope.mySelections,
enableCellEditOnFocus: true,
multiSelect: true,
afterSelectionChange: function() {
$scope.selectedIDs = [];
angular.forEach($scope.mySelections, function(item) {
$scope.selectedIDs.push(item.name)
});
},
columnDefs: [
{field:'id', displayName:'Id', cellTemplate: '<div class="ui-grid-cell-contents v-align-middle padding-20"><p>{{COL_FIELD}}</p></div>'},
{field:'name', displayName:'Name', cellTemplate: '<div class="ui-grid-cell-contents v-align-middle padding-20"><p>{{COL_FIELD}}</p></div>'}
]
};

Resources