I'm using ui-grid and I'm grouping the data, I will need to get the group headers and the counters. How can I get those values?
This is an example of the grid
$scope.gridOptions = {
enableFiltering: false,
enableColumnResize: true,
onRegisterApi: function (gridApi) {
$scope.gridApi = gridApi;
},
columnDefs: [
{ field: 'month',enableHiding: false, grouping: { groupPriority: 0 }, sort: { priority: 0, direction: 'desc' }},
{ field: 'facility',enableHiding: false,grouping: { groupPriority: 1 }, sort: { priority: 1, direction: 'asc' }},
...
{ field: 'categorymanager',enableHiding: false, displayName:'CM', grouping:{ groupPriority: 2 }, sort: { priority: 2, direction: 'asc' }},
]
};
You can get the values by writing a custom cellTemplate for the colDef. For example if you can define your template as:
let monthTemplate = '<div><div ng-if="!col.grouping || col.grouping.groupPriority === undefined || col.grouping.groupPriority === null || ' +
'( row.groupHeader && col.grouping.groupPriority === row.treeLevel )" class="ui-grid-cell-contents" ' +
'title="TOOLTIP">{{grid.appScope.getValue(COL_FIELD, row.treeNode.children )}}</div></div>';
Then define your method as:
$scope.getValue = function(item, treeRowEntity){
//item will hold month value
//iterate over treerowentity array and get values
//for example, if column required was facility
treeRowEntity[0].row.entity.facility
};
Related
I have a stored procedure that returns the first 4 columns(LineNumber, AttributeName, Source, MIC) along with the other columns that are dynamic. Dynamic meaning it can range from 150 to 1. Here in the screenshot example I have columns 40 to 29.
I was able to bring the data from back end to the controller and I was also able to display the the first 4 columns fine. But I need help to loop through the rest of the columns (For example in the screenshot the columns from 40 to 29. These columns are dynamic). THanks in advance.
$scope.gridOptionsVatMakeRpt = {
enableFullRowSelection: true,
enableRowHeaderSelection: false,
paginationPageSizes: [20, 40, 60],
paginationPageSize: 40,
rowHeight: 53,
enableFiltering: true,
enableCellEdit: false,
enableGridMenu: false,
rowTemplate:
'<div ng-class="{ \'grey\':grid.appScope.rowFormatter( row ) }">' +
' <div ng-repeat="(colRenderIndex, col) in colContainer.renderedColumns track by col.colDef.name" class="ui-grid-cell" ng-class="{ \'ui-grid-row-header-cell\': col.isRowHeader }" ui-grid-cell></div>' +
'</div>',
columnDefs: [
{
field: 'LineNumber', grouping: {
groupPriority: 0
},
width: '10%', visible: true
}
, {
field: 'AttributeName', grouping: {
groupPriority: 1
},
width: '10%', visible: true
}
, { field: 'Source', width: '10%', visible: true }
, { field: 'MIC', width: '10%', visible: true }
}
$scope.loadgridVatMakeRpt = function () {
$scope.loading = true;
console.log('loading grid');
LRWService.getVatMakeRpt('1', '1221209', '100000028', '2020-05-08', '2020-05-08').success(function (data) {
if (data === null || data.VatMakeRptList === null || data.VatMakeRptList.length === 0) {
$scope.error = true;
$scope.errorDescription = "No data found for selected criteria.";
} else {
$scope.gridOptionsVatMakeRpt.paginationPageSizes.push(
data.VatMakeRptList.length
);
var VatMakeRptList = data.VatMakeRptList;
$scope.gridOptionsVatMakeRpt.data = VatMakeRptList;
$scope.renderfields();
console.log(VatMakeRptList);
$scope.error = false;
}
}).finally(function () { $scope.loading = false; });
};
You can create columns dynamically inside the function loadgridVatMakeRpt eg. you as per your information you can iterate through the number of columns, post fixed set of columns and add one dynamic column for each iteration till the last entry.
Also find below documentation link for further dynamic behaviour if needed
Just note that, column should have field to which it should map to.
$scope.gridOptionsVatMakeRpt = {
enableFullRowSelection: true,
enableRowHeaderSelection: false,
paginationPageSizes: [20, 40, 60],
paginationPageSize: 40,
rowHeight: 53,
enableFiltering: true,
enableCellEdit: false,
enableGridMenu: false,
rowTemplate:
'<div ng-class="{ \'grey\':grid.appScope.rowFormatter( row ) }">' +
' <div ng-repeat="(colRenderIndex, col) in colContainer.renderedColumns track by col.colDef.name" class="ui-grid-cell" ng-class="{ \'ui-grid-row-header-cell\': col.isRowHeader }" ui-grid-cell></div>' +
'</div>',
columnDefs: [
{
field: 'LineNumber', grouping: {
groupPriority: 0
},
width: '10%', visible: true
}
, {
field: 'AttributeName', grouping: {
groupPriority: 1
},
width: '10%', visible: true
}
, { field: 'Source', width: '10%', visible: true }
, { field: 'MIC', width: '10%', visible: true }
}
$scope.loadgridVatMakeRpt = function () {
$scope.loading = true;
console.log('loading grid');
LRWService.getVatMakeRpt('1', '1221209', '100000028', '2020-05-08', '2020-05-08').success(function (data) {
if (data === null || data.VatMakeRptList === null || data.VatMakeRptList.length === 0) {
$scope.error = true;
$scope.errorDescription = "No data found for selected criteria.";
} else {
$scope.gridOptionsVatMakeRpt.paginationPageSizes.push(
data.VatMakeRptList.length
);
var VatMakeRptList = data.VatMakeRptList;
var keysArray = [];
keysArray = Object.keys(VatMakeRptList[0]);
for (var i = 4;i<keysArray.length;i++) {
$scope.gridOptionsVatMakeRpt.columnDefs.push({ name: keysArray[i], field: keysArray[i],width: <dynamic/fixed width>, visible: true});
}
$scope.gridOptionsVatMakeRpt.data = VatMakeRptList;
$scope.renderfields();
console.log(VatMakeRptList);
$scope.error = false;
}
}).finally(function () { $scope.loading = false; });
};
I am trying to set rows editable/not editable based on a flag in the data.
I can get this working outside an angular 1.5 component, but can't seem to access row.entity inside a controller in a component.
function memberDisplayCtrl ($scope, memberFactory,uiGridConstants) {
var ctrl = this;
ctrl.people = memberFactory.getMembers();
ctrl.checkStatus = function(ctrl){
// How do I do something like this:
// if (ctrl.row.entity.Status === 'Y') { return 'true'; } else {return 'false';}
};
ctrl.gridOptions = {
enableSorting: true,
enableCellEdit:false,
cellEditableCondition: ctrl.checkStatus(ctrl),
enableHorizontalScrollbar : 0,
enableVerticalScrollbar : 0,
enableColumnMenus: false,
minRowsToShow: ctrl.people.length,
columnDefs: [
{ displayName:'First Name', name: 'fname', enableCellEdit:true },
{ displayName:'Last Name', name: 'lname', enableCellEdit:true },
{ displayName:'Date of Birth', name: 'DOB', type:'date', enableCellEdit:true, cellFilter: 'date:"yyyy-MM-dd"'},
{ displayName:'Address', name: 'address', enableCellEdit:true},
{ displayName:'Status',name: 'Status', enableCellEdit: true}
],
data : ctrl.people
};
}
I'm pretty sure I have a scope problem but can't seem to figure it out. How do I access row.entity? I have an isolated scope inside my controller (since it is part of a component)
plunker here: https://plnkr.co/edit/Wz7gKs
Thanks
just pass a function to cellEditableCondition instead of executing it:
cellEditableCondition: ctrl.checkStatus
and note, that parameter received by that function is not current controller's this (aliased in your case as ctrl), but ui-grid's scope, so I renamed ctrl to scope:
function memberDisplayCtrl ($scope, memberFactory,uiGridConstants) {
var ctrl = this;
ctrl.people = memberFactory.getMembers();
ctrl.checkStatus = function(scope) {
return scope.row.entity.Status === 'Y'
};
ctrl.gridOptions = {
enableSorting: true,
enableCellEdit:false,
cellEditableCondition: ctrl.checkStatus,
enableHorizontalScrollbar : 0,
enableVerticalScrollbar : 0,
enableColumnMenus: false,
minRowsToShow: ctrl.people.length,
columnDefs: [
{ displayName:'First Name', name: 'fname', enableCellEdit:true },
{ displayName:'Last Name', name: 'lname', enableCellEdit:true },
{ displayName:'Date of Birth', name: 'DOB', type:'date', enableCellEdit:true, cellFilter: 'date:"yyyy-MM-dd"'},
{ displayName:'Address', name: 'address', enableCellEdit:true},
{ displayName:'Status',name: 'Status', enableCellEdit: true}
],
data : ctrl.people
};
}
also, I see your commented code:
if (ctrl.row.entity.Status === 'Y') {
return 'true';
}
else {
return 'false';
}
here you intend to return string variable in both cases which will always evaluated as boolean true, you should return boolean:
if (ctrl.row.entity.Status === 'Y') {
return true;
}
else {
return false;
}
which is equal to much shorter version:
return ctrl.row.entity.Status === 'Y';
plunker: https://plnkr.co/edit/KXbJ40?p=preview
How can I filter a complex expression mapping like "brand.title". Here is my fileds initialization :
$scope.gridOptions2.columnDefs = [
{ field: 'code', displayName: "Code" },
{ field: 'brand.title', displayName: "Brand", resizable: true },
];
And the filter :
$scope.singleFilter = function(renderableRows) {
var matcher = new RegExp($scope.selectedBrand);
renderableRows.forEach(function(row) {
var match = false;
['code', 'brand.title' ].forEach(function(field) {
if (row.entity[field].match(matcher)) {
match = true;
}
});
if (!match) {
row.visible = false;
}
});
return renderableRows;
};
Filtring on code field works fine but brand.title gives the following error :
TypeError: Cannot read property 'match' of undefined
The alternative is :
$scope.gridOptions2 = {
columnDefs : [
{ field: 'code', displayName: "Code", enableFiltering: true },
{ field: 'brand.title', displayName: "Brand", resizable: true, enableFiltering: true, filter: {
term : $scope.term }}
],
onRegisterApi : function(gridApi) {
$scope.gridApi = gridApi;
}
};
$scope.singleFilter = function() {
$scope.gridApi.grid.columns[2].filter.term = $scope.term;
};
maybe the title of my question is not proper, please feel free to update my title.
my json data is like
[
{ "AutoId": 2, "CustomerId": "1000AIRLIESST", "customerLastName": "John", "locationId": "2", "Address": "1000 AIRLIES ST Winnipeg " },
{ "AutoId": 2, "CustomerId": "1000AIRLIESST", "customerLastName": "John", "locationId": "186471", "Address": "1000 Airlies ST Winnipeg " },
{ "AutoId": 2, "CustomerId": "1000AIRLIESST", "customerLastName": "John", "locationId": "186752", "Address": "111 pineview rd ST Winnipeg " }
];
as you can see the autoId, customerId and lastname are same. I want to demonstrate this data in ui-grid like following picture. I want to common part of my data comes in main columns.
It is impossible to group two column with same grouping priority
groupPriorities should generally be sequential, if they're not then the next time getGrouping is called we'll renumber them to be sequential.
Defaults to undefined.
so my solution is like a cheat. first I use the aggregation function (max) for second column (customerLastname). then I used a custom directive to manipulate data.
you can see the result in plunker
The column definition of ui-grid
$scope.gridOptions = {
enableFiltering: true,
treeRowHeaderAlwaysVisible: false,
columnDefs: [
{
name: 'customerLastName',
displayName: 'Customer LastName',
width: 200,
treeAggregationType: uiGridGroupingConstants.aggregation.MAX,
cellTemplate: '<div class="ui-grid-cell-contents" > <fakemax val="{{COL_FIELD}}" /></div>'
},
{
name: 'Address',
width: 200,
},
{
name: 'CustomerId',
grouping: { groupPriority: 0 },
sort: { priority: 0, direction: 'desc' },
width: 200,
cellTemplate: '<div><div ng-if="!col.grouping || col.grouping.groupPriority === undefined || col.grouping.groupPriority === null ||' +
' ( row.groupHeader && col.grouping.groupPriority === row.treeLevel )" class="ui-grid-cell-contents" title="TOOLTIP">{{COL_FIELD CUSTOM_FILTERS}}</div></div>'
},
],
data: 'Customers',
onRegisterApi: function (gridApi) {
$scope.gridApi = gridApi;
}
};
please pay attention to fakemax directive which I used in the cellTemplate of customerLastName. the custom directive is so simple.
app.directive('fakemax', function () {
return function(scope, iElement, iAttrs) {
var value = iAttrs.val;
value = value.replace("max:", "");
iElement[0].innerHTML = value;
}
});
I've got a datagrid configured as follows:
<script>
angular.module("KendoDemos", [ "kendo.directives" ]);
function MyCtrl($scope) {
$scope.mainGridOptions = {
dataSource: {
transport: {
read: {
url: "http://localhost:8090/rest/mycodeapi/Salesman?app_name=mycode&fields=FirstName%2C%20LastName&include_count=true",
dataType : 'jsonp',
type: 'GET',
beforeSend: function (req) {
req.setRequestHeader('Authorization', 'b3pilsnuhsppon2qmcmsf7uvj6')
}
},
parameterMap: function(data, type) {
if (type == "read") {
// send take as "$top" and skip as "$skip"
return {
order: data.sort[0]['field'] + ' ' + data.sort[0]['dir'],
limit: data.pageSize,
offset: data.skip
};
}
}
},
schema: {
data : 'record',
total: 'meta.count'
},
pageSize: 5,
serverPaging: true,
serverSorting: true,
sort: { field: "SalesmanID", dir: "asc" }
},
sortable: true,
pageable: true,
mobile: 'phone',
columns: [{
field: "FirstName",
title: "First Name"
},{
field: "LastName",
title: "Last Name"
}]
};
}
</script>
Problem is: on 1st click of the any column, say FirstName, it sorts by ascending order which is fine.
On 2nd click it sorts by descending: still the expected behaviour.
On the 3rd click however, nothing happens and the console reveals "Uncaught TypeError: Cannot read property 'field' of undefined ". This means something happens to the data.sort array after the 2nd consecutive click.
Would appreciate any pointers.
On third click the sorting is removed. You can modify your script like following:
if (type == "read") {
var params = {
limit: data.pageSize,
offset: data.skip
};
if (data.sort && data.sort.length > 0)
params.order = data.sort[0]['field'] + ' ' + data.sort[0]['dir'];
return params;
}
I know this is a bit late, but I was facing the same challenge, and this is what I did to resolve the issue.
Change
sortable: true,
to
sortable: {
allowUnsort: false
},