Skip to content

Commit

Permalink
Merge pull request #1 from Boltmade/feature/custom-sort
Browse files Browse the repository at this point in the history
Add ability to specify a custom sorting function for a column
  • Loading branch information
tbroadley authored Oct 4, 2016
2 parents b5ec837 + 1c6202b commit e51f96f
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 17 deletions.
28 changes: 22 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ Empty Tables
By default the content for the empty table cell is set to `"No Items"`, however it can be changed via the `noDataText` configuration option (see below). It is inserted as one `<td>` spanning
all columns and placed inside a `<tr class="showIfLast">`, which is placed at the top of each table.

The message can be customized for each table by specifying the `ts-no-data-text` attribute on the same element as the `ts-wrapper`.
The message can be customized for each table by specifying the `ts-no-data-text` attribute on the same element as the `ts-wrapper`.
```html
<table ts-wrapper ts-no-data-text="Nothing to see here...">
```
Expand Down Expand Up @@ -195,7 +195,7 @@ angular
filterString += "</div>";
filterString += "</div>";
tableSortConfigProvider.filterTemplate = filterString;

var pagerString = "<div class='text-right'>";
pagerString += "<small class='text-muted'>Showing {{CURRENT_PAGE_RANGE}} {{FILTERED_COUNT === 0 ? '' : 'of'}} ";
pagerString += "<span ng-if='FILTERED_COUNT === TOTAL_COUNT'>{{TOTAL_COUNT | number}} {{TOTAL_COUNT === 1 ? ITEM_NAME_SINGULAR : ITEM_NAME_PLURAL}}</span>";
Expand Down Expand Up @@ -232,7 +232,7 @@ There are several tokens that can be used in the templates which will be replace
The name of the things listed in the table can be displayed in the filtering and pagination templates. They are named `"items"` collectively and `"item"` individually by default, but this can be customized in the global config, and per-table to be more specific as to what is being listed.

On a table just set the `ts-item-name` attribute on the same element as `ts-wrapper`. Set this as the singular version of the word, not the plural.

```html
<table ts-wrapper ts-item-name="product">
```
Expand Down Expand Up @@ -274,7 +274,7 @@ Another approach is to add the `ts-filter-fields` attribute to the same element
Set the `ts-per-page-options` attribute on the same element that `tw-wrapper` is set on to override the options for the number of items available per page.

Set the `ts-per-page-default` attribute on the same element that `tw-wrapper` is set on to override the default number of items available per page.

```html
<table ts-wrapper ts-per-page-options="[5, 10, 15, 30]" ts-per-page-default="15">
```
Expand Down Expand Up @@ -309,7 +309,7 @@ $scope.customFilterFn = function(item){
}
};
```

```html
<label>Enabled</label>
<select ng-model="customFilterValue">
Expand All @@ -334,4 +334,20 @@ $scope.customFilterFn = function(item){
</tr>
</tbody>
</table>
```
```

### Customized Sorting

It may be useful to customize how a particular column is sorted. For example, if a column can contain
numbers and strings, you may want the numbers to be sorted numerically and the strings to be sorted
lexicographically. To specify a custom sorting function, add a `ts-order-by` attribute to your
header element:

```html
<th ts-criteria="name" ts-order-by="numbersBeforeStrings">Name</th>
```

The function specified in the `ts-order-by` attibute should behave in the same way as a custom comparison
function passed to `Array.prototype.sort`. See
[MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)
for more details.
46 changes: 44 additions & 2 deletions example.html
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,28 @@ <h2><em>Click Select to reveal item details.</em></h2>
</tbody>
</table>

<h1>Angular Tablesort with a custom sort function on the Price column</h1>
<table class="table table-striped" ts-wrapper>
<thead>
<tr>
<th>Select</th>
<th ts-criteria="Id">Id</th>
<th ts-criteria="Name|lowercase">Name</th>
<th ts-criteria="Price|parseFloat" ts-default ts-order-by="centsThenDollars">Price</th>
<th ts-criteria="Quantity|parseInt">Quantity</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in items track by item.Id" ts-repeat>
<td><input type="checkbox"></td>
<td>{{item.Id}}</td>
<td>{{item.Name}}</td>
<td>{{item.Price | currency}}</td>
<td>{{item.Quantity}}</td>
</tr>
</tbody>
</table>

<h1>Empty table</h1>
<table class="table table-striped" ts-wrapper>
<thead>
Expand Down Expand Up @@ -127,7 +149,7 @@ <h1>Empty table without "No data" row</h1>
</tr>
</tbody>
</table>

</div>
</div>

Expand All @@ -151,12 +173,32 @@ <h1>Empty table without "No data" row</h1>
selected: false
});
}

$scope.noitems = [];

$scope.clickRow = function () {
alert('You clicked the row.');
}

function swapBeforeAndAfterDecimal(number) {
var beforeDecimal = Math.floor(number).toString();
var afterDecimal = number.toString().replace(/.*\./, '');

return afterDecimal + '.' + beforeDecimal;
}

$scope.centsThenDollars = function (a, b) {
var aSwapped = swapBeforeAndAfterDecimal(a);
var bSwapped = swapBeforeAndAfterDecimal(b);

if (aSwapped > bSwapped) {
return 1;
} else if (aSwapped === bSwapped) {
return 0;
} else {
return -1;
}
}
}
);

Expand Down
34 changes: 25 additions & 9 deletions js/angular-tablesort.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@ tableSortModule.directive('tsWrapper', ['$parse', '$compile', function( $parse,
return [$parse( expr ), null, false, name ? name : expr];
};

this.setSortField = function( sortexpr, element, name ) {
this.setSortField = function( sortexpr, element, name, sortBy ) {
var i;
var expr = parse_sortexpr( sortexpr, name );
expr.push(sortBy);
if( $scope.sortExpression.length === 1
&& $scope.sortExpression[0][0] === expr[0] ) {
if( $scope.sortExpression[0][2] ) {
Expand Down Expand Up @@ -119,10 +120,11 @@ tableSortModule.directive('tsWrapper', ['$parse', '$compile', function( $parse,
}
};

this.addSortField = function( sortexpr, element, name ) {
this.addSortField = function( sortexpr, element, name, sortBy ) {
var i;
var toggle_order = false;
var expr = parse_sortexpr( sortexpr, name );
expr.push(sortBy);
for( i=0; i<$scope.sortExpression.length; i=i+1 ) {
if( $scope.sortExpression[i][0] === expr[0] ) {
if( $scope.sortExpression[i][2] ) {
Expand Down Expand Up @@ -269,8 +271,18 @@ tableSortModule.directive('tsWrapper', ['$parse', '$compile', function( $parse,
return filteredArr;
};

function defaultSort( a, b ) {
if (a > b) {
return 1;
} else if (a === b) {
return 0;
} else {
return -1;
}
}

$scope.sortFun = function( a, b ) {
var i, aval, bval, descending, filterFun;
var i, aval, bval, descending, filterFun, sortBy;
for( i=0; i<$scope.sortExpression.length; i=i+1 ){
aval = $scope.sortExpression[i][0](a);
bval = $scope.sortExpression[i][0](b);
Expand All @@ -286,10 +298,11 @@ tableSortModule.directive('tsWrapper', ['$parse', '$compile', function( $parse,
bval = "";
}
descending = $scope.sortExpression[i][2];
if( aval > bval ) {
sortBy = $scope.sortExpression[i][4] || defaultSort;
if( sortBy(aval, bval) === 1 ) {
return descending ? -1 : 1;
}
else if( aval < bval ) {
else if( sortBy(aval, bval) === -1 ) {
return descending ? 1 : -1;
}
}
Expand Down Expand Up @@ -356,23 +369,26 @@ tableSortModule.directive('tsWrapper', ['$parse', '$compile', function( $parse,
tableSortModule.directive('tsCriteria', function() {
return {
require: "^tsWrapper",
scope: {
tsOrderBy: '='
},
link: function(scope, element, attrs, tsWrapperCtrl) {
var clickingCallback = function(event) {
scope.$apply( function() {
if( event.shiftKey ) {
tsWrapperCtrl.addSortField(attrs.tsCriteria, element, attrs.tsName);
tsWrapperCtrl.addSortField(attrs.tsCriteria, element, attrs.tsName, scope.tsOrderBy);
}
else {
tsWrapperCtrl.setSortField(attrs.tsCriteria, element, attrs.tsName);
tsWrapperCtrl.setSortField(attrs.tsCriteria, element, attrs.tsName, scope.tsOrderBy);
}
} );
};
element.bind('click', clickingCallback);
element.addClass('tablesort-sortable');
if( "tsDefault" in attrs && attrs.tsDefault !== "0" ) {
tsWrapperCtrl.addSortField( attrs.tsCriteria, element, attrs.tsName );
tsWrapperCtrl.addSortField( attrs.tsCriteria, element, attrs.tsName, scope.tsOrderBy );
if( attrs.tsDefault === "descending" ) {
tsWrapperCtrl.addSortField( attrs.tsCriteria, element, attrs.tsName );
tsWrapperCtrl.addSortField( attrs.tsCriteria, element, attrs.tsName, scope.tsOrderBy );
}
}
if( "tsFilter" in attrs) {
Expand Down

0 comments on commit e51f96f

Please sign in to comment.