Как вызвать событие $ destroy для уже удаленной области видимости элемента?

0

Рассмотрим следующую директиву:

class HasPermissionDirective {
    constructor(PermissionService) {
        this.restrict = 'A';
        this.priority = 1005;

        this.PermissionService = PermissionService;
    }

    compile(element, attrs) {
        let permission = _.trim(attrs.hasPermission),
            hide       = _.get(attrs, 'hideOnly'),
            $element   = angular.element(element);

        if (permission && !this.PermissionService.hasPermission(permission)) {
            if (!_.isUndefined(hide)) {
                hide = _.trim(hide);

                if (hide === 'visibility') {
                    $element.css('visibility', 'hidden');
                } else {
                    $element.hide();
                }
            } else {
                $element.remove();
            }
        }
    }

    link($scope, $element, attrs, ctrl) {
        $scope.$destroy();
    }
}

HasPermissionDirective.$inject = ['PermissionService'];

Проблема в том, что теперь $ scope. $ Destroy() выполняется всегда, для каждого элемента-области, к которой прикреплена директива (конечно).

Когда я теперь добавляю переменную-член "isRemoved" и устанавливаю ее в true, если элемент был удален и выполняет следующие функции связи:

if (this.isRemoved) {
    $scope.$destroy();
}

Разумеется, $ scope. $ Destroy() запускается для каждого объекта-сферы, как только удаляется хотя бы один элемент, поэтому директива обрабатывается как одноточечная, а не как экземпляр.

Я не могу добавить какую-либо информацию к узлу элемента, поскольку он, кажется, удаляется после компиляции и является только узлом комментария "ngInclude: undefined" (нет, я не удаляю узел, добавляю атрибут data и хочу его получить внутри функции ссылки: $element.data('remove', true) а затем хотите $ destroy и remove()). EDIT: Это похоже на transclude-поведение директивы ngInclude.

Если я удаляю $ scope. $ Destroy() из функции link и просто удаляю узел, директива ngInclude все еще работает...

Ват, я хочу? Я просто хочу удалить элемент из DOM во время компиляции, поскольку у текущего пользователя нет разрешения на просмотр этого элемента/директивы/представления, и я также хочу избежать дальнейшей обработки директив (в моем случае ng-include, который не должен быть лишним шаблоны запросов (так как наш сервер будет отвечать 401 в любом случае) и так далее).

UPDATE: Я думаю, мне нужен способ установить параметр terminal внутри функции компиляции, чтобы остановить обработку предстоящих директив. Моя проблема в том, что ngInclude работает, хотя элемент был удален ранее.

Теги:
angularjs-directive

1 ответ

1

Решение найдено! Я также должен использовать transclusion (было ясно после того, как я проверял impl ngIf) и его единственной возможной внутри (до/после) функции (-ов) ссылки, так что здесь impl. для тех, кто сталкивается с аналогичными проблемами:

class HasPermissionDirective {
    constructor(PermissionService) {
        this.restrict = 'A';
        this.priority = 1011; // high prio so the element is removed before all other directives can be processed
        this.transclude = 'element';
        this.$$tlb = true; // BAD! But w/o, transclusion for different directives won't work :(

        this.PermissionService = PermissionService;
    }

    preLink($scope, $element, attrs, ctrl, $transclude) {
        let $newScope = $scope.$new(),
            hide = _.get(attrs, 'hideOnly');

        $transclude($newScope, ($clone) => {
            if (!this.PermissionService.hasPermission(_.trim(attrs.hasPermission))) {
                if (!_.isUndefined(hide)) {
                    hide = _.trim(hide);

                    if (hide === 'visibility') {
                        $clone.css('visibility', 'hidden');
                    } else {
                        $clone.hide();
                    }
                } else {
                    $newScope.$destroy();
                    $newScope = null;

                    $clone.remove();
                    $clone = null;
                }
            } else {
                // in case the user has the permission we have to attach the element to the DOM (cause of transclusion)
                $element.after($clone);
            }
        });
    }
}

HasPermissionDirective.$inject = ['PermissionService'];

Я также выполнил аутсорсинг реализации контроллеру, чтобы я мог повторно использовать логику, но я не предоставил полный пример для разъяснения :)

Ещё вопросы

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