Как предотвратить, чтобы область действия была разделена между директивами n Angular?

Все мои директивы используют одну и ту же область видимости, и я хочу, чтобы мои директивы работали самостоятельно.

Директива:

app.directive('headerSort', function () {
    return {
        restrict: 'A',
        controller: function ($scope, $element, $attrs) {
            $scope.caption = $attrs.caption;

            $scope.doSort = function () {
                $scope.orderField = $attrs.headerSort;
                $scope.reverse = !$scope.reverse;
            };
        },
        template: '<div data-ng-click="doSort();">' +
                    '{{caption}}' +
                    '<i class="icon-sort"></i>' +
                  '</div>'
    };
});

HTML:

<th data-header-Sort="FullName" data-caption="Full name"></th>
<th data-header-Sort="FirsName" data-caption="First name"></th>
<th data-header-Sort="Age" data-caption="Age"></th>

В результате все столбцы имеют значение «Возраст» и сортируются по возрасту. Я хочу, конечно, чтобы каждый столбец сортировал свой собственный столбец. Как я могу этого добиться?

ОБНОВЛЕНИЕ: забыл упомянуть, что orderField и reverse используются в ng-repeat | orderBy:

<tbody id="customerRows" data-ng-repeat="customer in customers | orderBy:orderField:reverse">

person Martijn    schedule 31.05.2013    source источник
comment
Вас может заинтересовать директива ng-grid AngularUI @ angular-ui.github.io/ng- сетка   -  person Mike Pugh    schedule 31.05.2013


Ответы (2)


Каждый экземпляр вашей директивы должен иметь свой собственный заголовок, тип сортировки и свойство reverse. Таким образом, директиве потребуется собственная (дочерняя) область действия либо изолированная область (scope: {}), либо новая область (scope: true). Поскольку директива не является автономным/автономным компонентом, я бы не стал использовать изолированную область (см. также При написании директивы в AngularJS, как мне решить, нужна ли мне не новая область, новая дочерняя область, или новую изолированную область?).

С типом области, выбранным для директивы, тип сортировки и обратные значения могут быть переданы родителю через аргументы функции или могут быть установлены непосредственно в родительской области. Я предлагаю аргументы функции:

app.directive('headerSort', function () {
    return {
        scope: true,   // creates a new child scope
        link: function (scope, element, attrs) {
            scope.caption  = attrs.caption;
            scope.sortType = attrs.headerSort;
            scope.reverse  = false;
        },
        template: '<div data-ng-click="reverse=!reverse; doSort(sortType, reverse);">' +
             '{{caption}}</div>'
    };
});
function MyCtrl($scope) {
    $scope.orderField = "FirstName";
    $scope.reverse    = false;
    $scope.customers  = [ {FirstName: 'Martijn', Age: 22}, {FirstName: 'Mark', Age: 44}];
    $scope.doSort = function (sortType, reverse) {
        console.log('sorting',sortType, reverse);
        $scope.orderField = sortType;
        $scope.reverse    = reverse;
    };
}
<table>
    <th data-header-sort="FirstName" data-caption="First name"></th>
    <th data-header-sort="Age" data-caption="Age"></th>
    <tbody id="customerRows" data-ng-repeat="customer in customers | orderBy:orderField:reverse">
        <tr><td>{{customer.FirstName}}<td>{{customer.Age}}
    </tbody>
</table>

fiddle В скрипке, для простоты, я не включил Полное имя столбца.

person Mark Rajcok    schedule 31.05.2013
comment
Большое спасибо! Также для ссылок и дальнейшего объяснения! - person Martijn; 14.06.2013

Вам нужно «изолировать» область действия. Это даст каждому экземпляру директивы собственную область действия. Добавьте в определение директивы следующее:

scope: {},

Итак, ваше окончательное определение директивы будет выглядеть так:

app.directive('headerSort', function () {
    return {
        restrict: 'A',
        scope: {},
        controller: function ($scope, $element, $attrs) {
            $scope.caption = $attrs.caption;

            $scope.doSort = function () {
                $scope.orderField = $attrs.headerSort;
                $scope.reverse = !$scope.reverse;
            };
        },
        template: '<div data-ng-click="doSort();">' +
                    '{{caption}}' +
                    '<i class="icon-sort"></i>' +
                  '</div>'
    };
});

Видео Egghead.io подробно описывает изоляцию области. Вы можете просмотреть их здесь: http://www.egghead.io/

Видео с отдельными прицелами начинаются с урока №16.

person Polaris878    schedule 31.05.2013
comment
Спасибо. Имена столбцов отображаются неправильно, но щелчок по-прежнему не работает. Если так будет проще, я не знаю, где находится doSort. В области действия контроллера или области действия контроллера директивы. - person Martijn; 31.05.2013
comment
$scope.orderField установит свойство в изолированной области, а не в родительской области, поэтому это не сработает. - person Mark Rajcok; 31.05.2013
comment
Вы правы, Марк, вам, вероятно, лучше использовать дочернюю область. - person Polaris878; 01.06.2013