how to use a dynamic orderBy in a ng-repeat

2019-05-06 16:51发布

问题:

ive been reading on how to use a dynamic orderby with a ng-repeat but i stuck. The object I am working with looks like this:

 {
    "type": "Active",
    "properties": {
        "id": 105935,
        "name": "Museum Hill Estates",
        "show": false,
        "territoryId": 1996
    },
    "metrics": {
        "bld": {
            "type": "Unknown",
            "count": {
                "prod": 78,
                "custom": 90
            }
        },
        "inv": {
            "fut": 9,
            "vdl": 6,
            "mod": 1,
            "fin": 3,
            "uc": 3,
            "total": 22
        },
        "loe": {
            "bld": 11,
            "inv": 20,
            "size": 3,
            "activity": 9,
            "total": 43
        }
    },
    "geometry": {
        "type": "Point",
        "coordinates": [
            -105.93069,
            35.65802
        ]
    }
}

By default I need (desc) name,total loe, inventory(fut/vdl/mod/uc/fin/total) I have 3 checkboxes in a btn-group i want to use for changing the order. currently only the first one in the filter is working.

here is a working plunker plunker

 vm.sortByName = 'properties.name';
    vm.sortByLoeTotal = 'metrics.loe.total';
    vm.sortByInv = ['metrics.inv.fut','metrics.inv.vdl','metrics.inv.mod','metrics.inv.uc','metrics.inv.fin','metrics.inv.total'];

    vm.setSubdivisionSorting = function (filter) {
        if (filter === 'loe' && vm.loeFilter === true) {
            vm.sortByLoeTotal = 'metrics.loe.total';
            vm.loeFilter = false;
        }
        if (filter === 'loe' && vm.loeFilter === false) {
            vm.sortByLoeTotal = '-metrics.loe.total';
            vm.loeFilter = true;
        }
        if (filter === 'inventory' && vm.inventoryFilter === true) {
           vm.sortByInv = ['metrics.inv.fut', 'metrics.inv.vdl', 'metrics.inv.mod', 'metrics.inv.uc', 'metrics.inv.fin', 'metrics.inv.total'];
           vm.inventoryFilter = false;
        }
        if (filter === 'inventory' && vm.inventoryFilter === false) {
           vm.sortByInv = ['-metrics.inv.fut', '-metrics.inv.vdl', '-metrics.inv.mod', '-metrics.inv.uc', '-metrics.inv.fin', '-metrics.inv.total'];
           vm.inventoryFilter = true;
        }
        if (filter === 'subdivision' && vm.subdivisionFilter === true) {
            vm.sortByName = 'properties.name';
            vm.subdivisionFilter = false;
        }
        if (filter === 'subdivision' && vm.subdivisionFilter === false) {
            vm.sortByName = '-properties.name';
            vm.subdivisionFilter = true;
        }
    };

i just found a angular-filter module and included it in the punker in case someone believes that is a way to go.

回答1:

Have a look into this plunker. I've modified/cleaned the code quite abit so it's easier to read.

The arguments to the orderBy filter are prioritised from left to right. Which means that even if you specify multiple properties to order on and the target value of the first property are not the same, the second property is not used in sorting.

var orderBy = ['name', 'age'];

var data = [{
 name: 'Foo',
 age: 102
}, {
 name: 'Bar',
 age: 99999 // <-- not used in sorting since the name property differs
}];

Simply don't include the fields in the orderBy that you don't want to use to sort on; don't include them as a descending sort.

Also, you might want to take a look into something like $scope.$watch instead of applying ng-change on html elements. Keep your model state in the controller en let the view adjust to it.

Hope this helps.

Cheers.