Начальная точка Директивы угловой группировки

0

Я пытаюсь создать механизм группировки и фильтрации с несколькими предопределенными фильтрами. У меня есть набор неопределенных правил и некоторые предопределенные действия группировки, например "relativeDate" (сегодня, завтра, вчера, на этой неделе,...), "boolean" или. Набор действий должен быть расширяемым.

Мне удалось заставить это работать в контроллере. Но я хочу передать это на аутсорсинг в директиву, чтобы получить эту работу с другими коллекциями объектов. Проблема в следующем: мне нужно указать шаблон списка динамически.

Представьте себе следующие коллекции:

$scope.memosReceived = [
     { id: 1, from: 'Henry Ford', title: 'Want your Model T?', received: '2015-05-04T12:30:00', read: true },
     { id: 2, from: 'Oliver Newton', title: 'Look at this!', received: '2015-06-15T08:00:00', read: true }
     ...
];

$scope.memosSent = [
     { id: 1, to: 'Henry Ford', title: 'That is an old car', sent: '2015-05-04T12:35:21', read: true },
     { id: 2, to: 'Oliver Newton', title: 'Stop Spam', sent: '2015-06-15T08:01:47', read: false }
     ...
];

Теперь разметка должна выглядеть следующим образом:

<div ng-controller="controller">
    <h2>Received</h2>
    <grouped-list ng-model="memosReceived" item-var="received" grouping-options="groupingReceived">
        <h2>{{ received.title }} <sub>by {{ received.from }}</h2>
    </grouped-list>

    <h2>Sent</h2>
    <grouped-list ng-model="memosSent" item-var="sent" grouping-options="groupingSent">
        <h2>{{ sent.title }} <sub>to {{ sent.to }}</h2>
    </grouped-list>
</div>

Возможные варианты:

$scope.groupingReceived = [
    { modelKey: 'received', action: 'relativeDate', options: { [.. passed to grouping action, like value->name mapping ..] },
    { modelKey: 'read', action: 'boolean', options: { [...] } }];

$scope.groupingSent = [
    { modelKey: 'sent', action: 'relativeDate', options: { [.. passed to grouping action, like value->name mapping ..] },
    { modelKey: 'read', action: 'boolean', options: { [...] } }];

Представленный HTML должен выглядеть так: "PseudoHtml":

<div ng-controller="controller">
    <h2>Received</h2>
    <div class="grouped-list">
        <div class="filter-section">
            <button ng-click="openFilters = !openFilters>Open Filters</button>
            <div class="filter-options" ng-hide="!openFilters">
                <h4>Group by</h4>
                [selectbox given group actions] [selectbox sort ascending or descending]
                <h4>Filter by</h4>
                [build filters by similar to group actions given filter actions]
            </div>
        </div>
        <div class="group">
            <div class="group-header">
                <h3>Yesterday</h3>
            </div>
            <ul class="group-list">
                <li ng-repeat="received in ngModel | customFilters">
                    <!-- something like transclusion starts here -->
                    <h2>{{ received.title }} <sub>by {{ received.from }}</h2>
                    <!-- something like transclusion ends here -->            
                </li>
           </ul>
        </div>
        <div class="group">
            <div class="group-header">
                <h3>Last Week</h3>
            </div>
            <ul class="group-list">
                <li ng-repeat="received in ngModel | customFilters">
                    <!-- something like transclusion starts here -->
                    <h2>{{ received.title }} <sub>by {{ received.from }}</h2>
                    <!-- something like transclusion ends here -->            
                </li>
            </ul>
        </div>
    </div>

    <h2>Sent</h2>
    <div class="grouped-list">
        [... same like above ...]
    </div>
</div>

Я действительно борется с тем, как добиться такого поведения, где хранить несколько частей логики (например, действия группировки, пользовательские фильтры) и как правильно их перенести.

Может быть, кто-то может дать мне хорошую отправную точку для этого.

Теги:
angular-directive
angularjs-scope
angularjs-ng-repeat

1 ответ

0

Вы можете создать собственный фильтр и вызвать его из контроллера вашей директивы.

Внутри этого фильтра вы можете решить, какое действие фильтра следует запускать, передавая параметры фильтру.

Я бы назвал это из контроллера вместо шаблона, потому что там вы можете упростить цепочку фильтров.

Пожалуйста, просмотрите демо внизу или в этом jsfiddle.

Во время добавления моего кода в SO я обнаружил ошибку (не отображающую элемент) в моем коде с более новой версией AngularJS. Не уверен, что это такое, но с работой 1.2.1. Я проверю это позже. Похоже на проблему.

angular.module('demoApp', [])
    .filter('aw-group', function($filter) {
        var filterMethods = {
            relativeDate: function(input, action) {
                console.log('relative date called', input);
                return input; // do the translation to relative date here
            },
            filterByNumber: function(input, action, options) {
                // if you need mor parameters
                return $filter('filter')(input, options.number);
            },
           otherFilter: {
           }
        };
        
        return function(input, action, options) {
            return filterMethods[action](input, action, options);
        };
    })   
    .directive('groupedList', function () {
    return {
        restrict: 'E',
        scope: {
            model: '=',
            itemVar: '=',
            filter: '='
        },
        transclude: true,
        template: '<ul><li ng-repeat="item in filteredModel" ng-transclude>'+
        '</li></ul>',
        controller: function($scope, $filter) {
            //console.log($scope.filter);
            
            $scope.filteredModel = $filter('aw-group')($scope.model, 'filterByNumber', { number: 2 }); // passing action from $scope.filter.action as second parameter, third is an options object
        }
    };
})
    .controller('mainController', function () {
    this.data = [{
        title: 'Test1',
        from: 'tester1'
    }, {
        title: 'Test2',
        from: 'tester1'
    }, {
        title: 'Test3',
        from: 'tester1'
    }, ];
    this.groupingReceived = [{
        modelKey: 'received',
        action: 'relativeDate',
        options: {},
        modelKey: 'read',
        action: 'boolean',
        options: {}
    }];

    this.memosReceived = [{
        id: 1,
        from: 'Henry Ford',
        title: 'Want your Model T?',
        received: '2015-05-04T12:30:00',
        read: true
    }, {
        id: 2,
        from: 'Oliver Newton',
        title: 'Look at this!',
        received: '2015-06-15T08:00:00',
        read: true
    }];

});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<div ng-app="demoApp" ng-controller="mainController as ctrl">
    <grouped-list model="ctrl.data" item-var="received" filter="ctrl.groupingReceived">
         <h2>{{item.title}}<sub>{{item.from}}</sub></h2>

    </grouped-list>
</div>
  • 0
    Это проблема. ng-transclude не работает с ng-repeat в более новых версиях. Я попробовал то же самое.
  • 0
    Хорошо, спасибо за указание на эту проблему. Я обновил тот же jsFiddle. Пожалуйста, посмотрите. Теперь это работает. Если я правильно понял, новая директива вводит область действия ng-repeat область включения. Я взял код из plunkr из этой дискуссии об этой проблеме.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню