问题
I have checked all stackoverflow posts related to ui-grid sorted rows without any success so I am opening one more question.
SHORT : Need a way to get sorted rows following current sorting criteria.
My problem is that I have an instance of UI Grid with pagination and I can not get the sorted data after it was added using a $mdDialog
modal. It is shown at the right position in the tabel, but behind, in all objects it is stored the new element is on the last position.
I call the ui-grid instance using a service to keep all stuff in one place:
// Default service for init a ui-grid instance
app.serivce('testService', function(){
var defaultGridOptions = {
enableColumnMenus: false,
enablePaginationControls: true,
paginationPageSizes: [5],
multipleSorting: false,
treeRowHeaderAlwaysVisible: false,
paginationPageSize: 5,
enableHorizontalScrollbar: uiGridConstants.scrollbars.NEVER,
enableVerticalScrollbar: uiGridConstants.scrollbars.NEVER
};
// Each columns sort rule
// Position 0 from columnsOrder sorts position 0 from columnDefs and so on
var defaultColSort = [{
sort: { direction: uiGridConstants.ASC, priority: 0 }
}];
this.createGridOptions = function (gridData, columnDefs, gridOpts) {
gridOpts = typeof gridOpts !== 'undefined' ? gridOpts : {};
var gridOptions = angular.extend({}, defaultGridOptions, gridOpts);
for(var i = 0; i < defaultColSort.length; i++)
columnDefs[i] = angular.extend({}, defaultColSort[i], columnDefs[i]);
gridOptions.data = gridData;
gridOptions.columnDefs = columnDefs;
return gridOptions;
};
// The metod that should move to the desired page
this.jumpToGridItem = function(api, entry) {
var idx = -1;
var page = 0;
var sortedData = null;
// NEED A WAY TO GET SORTED DATA HERE
//idx = sortedData.indexOf(entry); -> checks the position of the new added item
if (idx == -1)
return false;
// Calculate the page where the element exists
page = Math.ceil(idx/api.grid.options.paginationPageSize);
// Jump to page
api.pagination.seek(page);
};
})
Here is my controller :
app.controller('testController', ['$scope', '$mdDialog', 'testService', function($scope, $mdDialog, testService){
var columnDefs = [
{
field: 'identifier',
name: 'Identifier'
}
];
var dummyData = [{ identifier: "Item" }, { identifier: 'Item 1' }, { identifier: "Item 2" }, { identifier: "Item 3" }];
var gridOptions = $scope.gridOptions = testService.createGridOptions(dummyData, columnDefs);
gridOptions.onRegisterApi = function (gridApi) {
$scope.gridApi = gridApi;
};
$scope.add = function () {
$mdDialog.show({
controller: function($mdDialog) {
var data = $scope.identifierVal;
$mdDialog.hide(data);
},
templateUrl: 'add.html',
parent: angular.element(document.body)
}).then(function (entry) {
// Data received when the modal is hidden
$scope.gridOptions.data.push(entry);
testService.jumpToGridItem($scope.gridApi, entry);
});
};
}]);
Right now I am appending the data with push()
, this could be one reason, I think.
The method I have to update is jumpToGridItem
, which actually should focus the page where the item was added.
Thank you
PS : Sorry for not posting a plnkr, I will do bit later if it is needed.
回答1:
I finally found a way to achieve what I initially wanted. I ve found it a day after posting the question but I was busy enough to post the answer. The code below can be also found in a plnkr. It looks for a certain entry and goes to the page where it can be found.
I wanted this to focus a dynamically added entry in a ui-grid table from a dialog (modal form):
Controller :
var app = angular.module('stefanz', ['ui.grid', 'ui.grid.pagination']);
app.controller('MyCtrl', ['$scope', 'UIGridCustom', '$http', function($scope, UIGridCustom, $http){
// A part of data copied from ui-grid demos
var data = [{"name": "Ethel Price", "gender": "female", "company": "Enersol" },{"name": "Claudine Neal", "gender": "female", "company": "Sealoud" },{"name": "Beryl Rice", "gender": "female", "company": "Velity" },{"name": "Wilder Gonzales", "gender": "male", "company": "Geekko" },{"name": "Georgina Schultz", "gender": "female", "company": "Suretech" },{"name": "Carroll Buchanan", "gender": "male", "company": "Ecosys" },{"name": "Valarie Atkinson", "gender": "female", "company": "Hopeli" },{"name": "Schroeder Mathews", "gender": "male", "company": "Polarium" },{"name": "Lynda Mendoza", "gender": "female", "company": "Dogspa" },{"name": "Sarah Massey", "gender": "female", "company": "Bisba" },{"name": "Robles Boyle", "gender": "male", "company": "Comtract" },{"name": "Evans Hickman", "gender": "male", "company": "Parleynet" },{"name": "Dawson Barber", "gender": "male", "company": "Dymi" }];
var colDefs = [{
label: "name",
name: "name"
}, {
label: "gender",
name: "gender"
}, {
label: "company",
name: "company"
}];
// Call the service for init
var gridOptions = $scope.gridOptions = UIGridCustom.createGridOptions(data, colDefs);
gridOptions.onRegisterApi = function(api) {
$scope.gridApi = api;
}
$scope.getItemPage = function(name) {
UIGridCustom.jumpToGridItem($scope.gridApi, name);
}
}]);
app.service('UIGridCustom', ['uiGridConstants', 'utils', function(uiGridConstants, utils){
var defaultGridOptions = {
enableColumnMenus: false,
enableHorizontalScrollbar: uiGridConstants.scrollbars.NEVER,
enableVerticalScrollbar: uiGridConstants.scrollbars.NEVER,
enablePaginationControls: false,
paginationPageSize: 5,
multipleSorting: true
};
// Each columns sort rule
// Position 0 from columnsOrder sorts position 0 from columnDefs and so on
// Could be overwritten into columnDefs
// Docs : http://ui-grid.info/docs/#/api/ui.grid.class:GridOptions
var defaultColSort = [];
//1st column default sorting
defaultColSort[{
sort: { direction: uiGridConstants.ASC, priority: 0 }
}];
// For sorting 2nd column
// defaultColSort[1] = {
// sort: { direction: uiGridConstants.ASC, priority: 0 }
// };
this.createGridOptions = function (gridData, columnDefs, stefanzGridOpts) {
// Overwrite defaults with custom passed options for grid
var stefanzGridOpts = typeof stefanzGridOpts !== 'undefined' ? stefanzGridOpts : {};
var gridOptions = angular.extend({}, defaultGridOptions, stefanzGridOpts);
// Force sorting following the default/custom column sort
for(var i = 0; i < defaultColSort.length; i++)
columnDefs[i] = angular.extend({}, defaultColSort[i], columnDefs[i]);
// Grid init
gridOptions.data = gridData;
gridOptions.columnDefs = columnDefs;
return gridOptions;
};
this.jumpToGridItem = function(api, name) {
var idx = 0;
var page = 0;
var sorting = prepareCriteria(api.grid.getColumnSorting());
var data = dataObjectSort(prepareRows(api.grid.rows), sorting);
entry = getEntryByName(data, name);
idx = data.indexOf(entry) + 1;
if (!idx)
return false;
// Calculate the page where the element exists
page = Math.ceil(idx/api.grid.options.paginationPageSize);
alert(name + 'is found on page ' + page);
// Jump to page
api.pagination.seek(page);
};
// Takes the row's entity and put in a new array as a top-level item
// Userful for further data handling
var prepareRows = function(rows) {
if (rows.length == 0)
return false;
var preparedRows = [];
rows.forEach(function(row){
// Do not need to handle the rows that are not in current filter (hidden)
if (row.visible == false)
return true;
preparedRows.push(row.entity);
});
return preparedRows;
};
// We are comparing whole enter and as a parameter we are sending a name
var getEntryByName = function(data, searchedName) {
for(var i = 0; i < data.length; i++) {
if (data[i]['name'] == searchedName)
return data[i];
}
return false;
}
var dataObjectSort = function(data, criteria) {
return data.sort(utils.dynamicSortMultiple(criteria));
};
var prepareCriteria = function(colSorting) {
var sorting = [];
var fields = [];
// Take just needed fields
colSorting.forEach(function(column){
sorting.push({
field: column.field,
direction: column.sort.direction,
priority: column.sort.priority
})
});
// Sort criterias by priority - UI grid works like this
// Reason : http://ui-grid.info/docs/#/api/ui.grid.class:GridOptions.columnDef#properties_sort
sorting.sort(function(a, b){
if (a.priority < b.priority) return -1;
else if (a.priority > b.priority) return 1;
else return 0;
});
// Prepare fields for sorting
sorting.forEach(function(sort){
// Dymanic sort (above) needs "-" sign for descendent direction
if (sort.direction != uiGridConstants.ASC)
sort.field = '-' + sort.field;
fields.push(sort.field);
});
return fields;
};
}]);
// Keep utils methods into a separate service
// Here all sorting methods will appear
app.service('utils', function(){
function getJsonValue(obj, path) {
if (!path || path == '')
return obj;
path = path.split('.');
var len = path.length;
for (var i = 0; i < len - 1; i++) {
var prop = path[i].split(/\[([^\]]+)]/); // indication[4] => [indication, 4]; indication => [indication]
if (prop.length == 1) {
obj = obj[prop[0]];
} else {
obj = obj[prop[0]][prop[1]];
}
}
var prop = path[len - 1].split(/\[([^\]]+)]/); // indication[4] => [indication, 4]; indication => [indication]
if (prop.length == 1) {
return obj[prop[0]];
} else {
if (prop.length == 2) {
return obj[prop[0]][prop[1]];
} else {
if(prop.length ==3) {
return obj[prop[0]][prop[1]]; // this is a hack!
} else {
return obj[prop[0]][prop[1]][prop[3]]; // this is a hack!
}
}
}
};
//http://stackoverflow.com/questions/1129216/sort-array-of-objects-by-string-property-value-in-javascript/4760279#4760279
function dynamicSort(property) {
var sortOrder = 1;
if(property[0] === "-") {
sortOrder = -1;
property = property.substr(1);
}
return function (a,b) {
var aInsensitive = getJsonValue(a, property).toLowerCase();
var bInsensitive = getJsonValue(b, property).toLowerCase();
var result = (aInsensitive < bInsensitive) ? -1 : (aInsensitive > bInsensitive) ? 1 : 0;
return result * sortOrder;
}
};
function dynamicSortMultiple(props) {
return function (obj1, obj2) {
var i = 0, result = 0, numberOfProperties = props.length;
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(props[i])(obj1, obj2);
i++;
}
return result;
}
};
return {
getJsonValue: function(obj, path) {
return getJsonValue(obj, path);
},
dynamicSort: function(property) {
return dynamicSort(property);
},
dynamicSortMultiple: function(props) {
return dynamicSortMultiple(props);
}
}
});
HTML
<!DOCTYPE html>
<html ng-app="stefanz">
<head>
<script data-require="angularjs_1_3_15@*" data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular.min.js"></script>
<script data-require="angularjs_1_3_15@*" data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular-animate.min.js"></script>
<script data-require="angularjs_1_3_15@*" data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular-aria.min.js"></script>
<script data-require="jquery@*" data-semver="2.1.4" src="https://code.jquery.com/jquery-2.1.4.js"></script>
<link data-require="ui-grid@*" data-semver="3.0.7" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/3.0.7/ui-grid.css" />
<script data-require="ui-grid@*" data-semver="3.0.7" src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/3.0.7/ui-grid.js"></script>
<script data-require="bootstrap@~3.3.5" data-semver="3.3.6" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="MyCtrl">
<div ui-grid="gridOptions" ui-grid-pagination class="grid"></div>
<div class="centerAlignedText">
<ul>
<li><a ng-click="getItemPage('Ethel Price')">Get Ethel Price</a></li>
<li><a ng-click="getItemPage('Schroeder Mathews')">Get Schroeder Mathews</a></li>
<li><a ng-click="getItemPage('Dawson Barber')">Get Dawson Barber</a></li>
<li><a ng-click="getItemPage('Sarah Massey')">Get Sarah Massey</a></li>
</ul>
</div>
<div class="centerAlignedText" ng-if="gridOptions.totalItems > 0">
<div class="paginationButtonsIcon boldText" style="width: 100px; display: inline-block;">
<md-button ng-if="gridApi.pagination.getPage() > 1" class="paginationButtons" ng-click="gridApi.pagination.previousPage()" style="width: 90px;">
<span class="notTransformedText boldText">Previous</span>
</md-button>
</div>
<div ng-repeat="n in gridApi.pagination.getTotalPages()" style="display: inline-block;">
<md-button ng-if="(gridApi.pagination.getTotalPages() < 11)
|| (gridApi.pagination.getPage() < 7 && n < 10)
|| (n > gridApi.pagination.getPage() - 7 && n < gridApi.pagination.getPage() + 4)
|| (gridApi.pagination.getPage() > gridApi.pagination.getTotalPages() - 5 && n > gridApi.pagination.getTotalPages() - 11)" class="paginationButtons md-mini md-icon-button md-primary" ng-click="gridApi.pagination.seek($index + 1)">
<span class="paginationButtonsIcon boldText" ng-if="gridApi.pagination.getPage() === $index + 1">
{{$index + 1}}
</span>
<span class="paginationButtonsIcon" ng-if="gridApi.pagination.getPage() !== $index + 1">
{{$index + 1}}
</span>
</md-button>
</div>
<div class="paginationButtonsIcon boldText" style="width: 100px; display: inline-block;">
<md-button ng-if="gridApi.pagination.getPage() < gridApi.pagination.getTotalPages()" class="paginationButtons md-icon-button md-primary" ng-click="gridApi.pagination.nextPage()" style="width: 90px;">
<span class="notTransformedText boldText">Next</span>
</md-button>
</div>
</div>
</body>
</html>
来源:https://stackoverflow.com/questions/35129218/ui-grid-get-sorted-items-with-pagination