Ryan - Llaver Ryan - Llaver - 3 months ago 12
Javascript Question

OrderBy filter failing if expression contains a dot

I have a dynamically changing orderBy filter in angular.

My HTML calls an updateOrder() method that takes a parameter 'date', 'value', 'seller.name', 'buyer.name', etc.:

<button type="button" ng-click="updateOrder('date')" class="btn btn-default navbar-btn">Date</button>
<button type="button" ng-click="updateOrder('value')" class="btn btn-default navbar-btn">Valuation</button>
<button type="button" ng-click="updateorder('seller.name')" class="btn btn-default navbar-btn">Alphabetical</button>


My updateOrder() method detects whether the order needs to be reversed and with what to order the list by:

$scope.order = 'date';
$scope.reverse = true;
let current = $scope.order;
$scope.updateOrder = function(order) {
console.log(order);
if(current === order) {
$scope.reverse = !$scope.reverse;
} else if(!$scope.reverse) {
$scope.reverse = true;
$scope.order = order;
current = order;
} else {
$scope.order = order;
current = order;
}
}


And then my ng-repeat div uses this order filter:

orderBy:order:reverse


For some reason, whenever I pass an argument with a dot (period), the filter fails and the order doesn't change. Due to other limitations, I would prefer not to change my database schema to not have subcategories (buyer.name, seller.name, etc.). Is there a way around this?

Lex Lex
Answer

There's no issue with ordering by a dot-notated property. The issue is that you have ng-click="updateorder('seller.name')" and it should be ng-click="updateOrder('seller.name')". You have a lowercase "o" on your function call. Working sample:

angular.module('app', [])
    .controller('ctrl', function($scope) {
        $scope.order = 'date';
        $scope.reverse = true;
        let current = $scope.order;
        $scope.updateOrder = function(order) {
            if (current === order) {
                $scope.reverse = !$scope.reverse;
            } else if (!$scope.reverse) {
                $scope.reverse = true;
                $scope.order = order;
                current = order;
            } else {
                $scope.order = order;
                current = order;
            }
        }

        $scope.items = [{
            date: new Date('2016-01-01'),
            value: 100,
            seller: {
                name: 'Smith'
            }
        }, {
            date: new Date('2016-05-01'),
            value: 50,
            seller: {
                name: 'Smiley'
            }
        }, {
            date: new Date('2016-03-01'),
            value: 25,
            seller: {
                name: 'Jones'
            }
        }, {
            date: new Date('2016-08-01'),
            value: 500,
            seller: {
                name: 'Johnson'
            }
        }];
    });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
    <div>
        <button type="button" ng-click="updateOrder('date')" class="btn btn-default navbar-btn">Date</button>
        <button type="button" ng-click="updateOrder('value')" class="btn btn-default navbar-btn">Valuation</button>
        <button type="button" ng-click="updateOrder('seller.name')" class="btn btn-default navbar-btn">Alphabetical</button>
    </div>
    <table>
        <tr>
            <th>Date</th>
            <th>Value</th>
            <th>Seller</th>
        </tr>
        <tr ng-repeat="item in items | orderBy:order:reverse">
            <td>{{item.date | date: "M/d/yyyy"}}</td>
            <td>{{item.value}}</td>
            <td>{{item.seller.name}}</td>
        </tr>
    </table>
</div>

Comments