【问题标题】:AngularJS orderBy - Sort by string property of an object?AngularJS orderBy - 按对象的字符串属性排序?
【发布时间】:2017-03-10 17:34:50
【问题描述】:

我正在尝试按添加日期和列出的优先级对任务列表中的项目进行排序。我已经按日期进行了排序,但是如何对项目进行排序,以便将具有“HIGH”属性的项目排在列表的首位?

编辑:当从任务列表上方的“排序依据”选择框中选择此选项时,我需要它按 HIGH 排序。

Codepen:http://codepen.io/anon/pen/ryyQzy.

HTML:

<md-list class="md-padding">

                   <div layout="row">

                        <md-input-container class="md-block" flex="70">

                            <input type="text" ng-model="search" name="search" placeholder="Search by Task Name"></input>  

                        </md-input-container>

                        <md-input-container flex="30">

                            <md-select name="priority" ng-model="task.priority" placeholder="Sort By">

                                <md-option value="Low">Newest First</md-option>

                                <md-option value="HIGH">High Priority First</md-option>

                            </md-select>

                        </md-input-container>

                    </div>

                    <md-subheader class="md-no-sticky">Current Tasks ({{taskList.length}})</md-subheader> 

                    <md-list-item class="md-3-line" ng-repeat="task in taskList | orderBy:sortByNewest | filter:search">

                       <div class="md-list-item-text" layout="column">

                            <p>{{task.name}}</p>

                            <p>Priority: {{task.priority}}</p>

                            <span class="weak">Added {{task.addedOn | date: 'medium'}}</span>

                        </div>

                        <md-checkbox class="md-secondary" ng-model="task.completed"></md-checkbox>

                        <md-divider ng-if="!$last"></md-divider>

                    </md-list-item>

                </md-list>

JS:

var app = angular.module('todoApp', ['ngMaterial']);

function menuController ($scope, $mdDialog) {
    var originatorEv;
    this.openMenu = function($mdOpenMenu, ev) {
        originatorEv = ev;
        $mdOpenMenu(ev);
    };
};  

app.controller('todoController', function($scope, $mdDialog, $mdToast, $filter) {

    $scope.sortByNewest = '-addedOn';
    //$scope.sortByPriority = ' ';

    $scope.taskList = [
        { name: 'Task 1', priority: 'Low', completed: false, addedOn: 1488722128000 },
        { name: 'Task 2', priority: 'HIGH', completed: false, addedOn: 1488722128000 },
    ];

    $scope.addTask = function() {
        if (angular.isUndefined($scope.taskName) || $scope.taskName.length === 0) {
            var alert =  $mdDialog.alert()
                .parent(angular.element(document.querySelector('#popupContainer')))
                .clickOutsideToClose(true)
                .title('Error')
                .textContent('You must enter a task name and select a priority level')
                .ok('Close');
            $mdDialog.show( alert )
                .finally(function() {
                    alert = undefined;
                });
        }
        else {
            $scope.taskList.push({name: $scope.taskName, priority: $scope.task.priority, addedOn: Date.now()});
            $scope.taskName = "";
            $scope.task.priority = "";
            var pinTo = $scope.getToastPosition();
            $mdToast.show (
                $mdToast.simple()
                .textContent('Task Added')
                .position(pinTo)
                .hideDelay(3000)
            )
        }
    };

    $scope.selectAll = function() {
        angular.forEach($scope.taskList, function(task) {
            task.completed = true;
        });  
    };

    $scope.selectNone = function() {
        angular.forEach($scope.taskList, function(task) {
            task.completed = false;
        });  
    };

    $scope.delete = function(ev) {

        var completedTasks = $filter('filter')($scope.taskList, { completed: true}, true);

        if (completedTasks.length > 0) {
            console.log('show dialog box to confirm');   
            var confirm = $mdDialog.confirm()
                .title ('Are you sure you want to delete the selected tasks?')
                .textContent ('Deleted tasks can\'t be recovered.')
                .targetEvent (ev)
                .ok ('Confirm')
                .cancel ('Cancel')
            clickOutsideToClose: false;
            $mdDialog.show(confirm).then(function() {
                if (completedTasks.length > 1) {
                    var pinTo = $scope.getToastPosition();
                    $mdToast.show (
                        $mdToast.simple()
                        .textContent('Tasks Deleted')
                        .position(pinTo)
                        .hideDelay(3000)
                    )
                }
                else {
                    var pinTo = $scope.getToastPosition();
                    $mdToast.show (
                        $mdToast.simple()
                        .textContent('Task Deleted')
                        .position(pinTo)
                        .hideDelay(3000)
                    )
                }
                $scope.status = 'Tasks Deleted';
                var i = $scope.taskList.length;
                while (i--) {
                    var task = $scope.taskList[i];
                    if(task.completed) {
                        $scope.taskList.splice(i, 1);
                    }
                }

            }, 
            function() {
                $scope.status = 'Deletion Cancelled';
            });
        } 

        else {
            $mdDialog.show(
                $mdDialog.alert()
                    .parent(angular.element(document.querySelector('#popupContainer')))
                    .clickOutsideToClose(true)
                    .title('Error')
                    .textContent('You must select at least one task to delete.')
                    .ok('Close')
                    .targetEvent(ev)
            );
        }
    };

    function DialogController($scope, $mdDialog) {
        $scope.hide = function() {
            $mdDialog.hide();
        };

        $scope.cancel = function() {
            $mdDialog.cancel();
        };

        $scope.answer = function(answer) {
            $mdDialog.hide(answer);
        };
    };

    var last = {
        bottom: false,
        top: true,
        left: false,
        right: true
    };

    $scope.toastPosition = angular.extend({},last);

    $scope.getToastPosition = function() {
        sanitizePosition();
        return Object.keys($scope.toastPosition)
        .filter(function(pos) { return $scope.toastPosition[pos]; })
        .join(' ');
    };

    function sanitizePosition() {
        var current = $scope.toastPosition;
        if ( current.bottom && last.top ) current.top = false;
        if ( current.top && last.bottom ) current.bottom = false;
        if ( current.right && last.left ) current.left = false;
        if ( current.left && last.right ) current.right = false;
        last = angular.extend({},current);
    };

});

app.controller('toastController', function($scope, $mdToast) {
    $scope.closeToast = function() {
        $mdToast.hide();
    }

});

【问题讨论】:

  • 我不知道是不是只有我一个人,但我在这里看到很多代码(可能与问题无关),如果是,请考虑提供Minimal, Complete, and Verifiable example if如果我错了,可以或纠正我。
  • 我没有删减代码,因为我不知道你想要什么,而且我会单独包含 codepen 链接,但我显然不能。

标签: javascript angularjs sorting


【解决方案1】:

orderBy 需要它应该排序的对象的属性名称。因此,select 中的 options 应该像这样定义这些属性名称:

<md-select name="sortBy" placeholder="Sort By" ng-model="sortBy">
  <md-option value="addedOn">Newest First</md-option>
  <md-option value="priority">High Priority First</md-option>
</md-select>

如果orderBy 在这些属性中遇到字符串,它将按字母顺序对数组进行排序。所以这对你来说已经很方便了,因为 High 在 Low 之前。

来自 Angular 文档:

默认的内置比较器对于大多数用例应该足够了。简而言之,它比较数字的数字、字符串的字母顺序(并且不区分大小写),对于对象回退到使用它们在原始集合中的索引,并按类型对不同类型的值进行排序。

https://docs.angularjs.org/api/ng/filter/orderBy

【讨论】:

    【解决方案2】:

    您需要使用ng-model="search.name" and ng-model="search.priority"。然后它将从search对象中读取所有搜索条件。(filter:search)

    查看更新的Codepen

    请更新您的视图,如下所示: 按任务名称模型搜索 ng-model="search.name" 而不是 ng-model="search" 按模型排序为ng-model="search.priority" 而不是ng-model="sortBy"

    <div layout="row">
    
      <md-input-container class="md-block" flex="70">
    
        <input type="text" ng-model="search.name" name="search" placeholder="Search by Task Name"></input>
    
      </md-input-container>
    
      <md-input-container flex="30">
    
        <md-select name="priority" ng-model="search.priority" placeholder="Sort By">
    
          <md-option value="Low">Newest First</md-option>
    
          <md-option value="HIGH">High Priority First</md-option>
    
        </md-select>
    
      </md-input-container>
    
    </div>
    

    【讨论】:

    • @nick 回答你的问题了吗?
    猜你喜欢
    • 2013-01-11
    • 2019-08-02
    • 1970-01-01
    • 2016-02-25
    • 2021-06-27
    相关资源
    最近更新 更多