0
votes

As the title says I am trying to set disabled to material component using a directive. I've tried various ways, using ElementRef, Renderer, Renderer2 and querySelector. Nothing seems to be working.

Here it my code. Any help is appreciated.

import { Directive, Input, TemplateRef, ViewContainerRef, Renderer2, ElementRef } from '@angular/core';
import { PermissionType } from './permission-type.enum';
import { Resource } from './resource.enum';
import { PermissionManagerService } from './permission-manager.service';

@Directive({
  selector: '[appIsGranted]'
})
export class IsGrantedDirective {

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef,
    private permissionManagerS: PermissionManagerService,
    private _renderer: Renderer2,
    private el: ElementRef
  ) { }

  @Input() set appIsGranted(permission: Array<string>) {
    this.isGranted(
      permission[0] as Resource,
      permission[1] as PermissionType
    )
  }

  private isGranted(resource: Resource, permissionType: PermissionType) {
    if(this.permissionManagerS.isGranted(resource, permissionType)) {
      this.viewContainer.createEmbeddedView(this.templateRef);
    } else {
      let view = this.viewContainer.createEmbeddedView(this.templateRef);
      let rootElem = view.rootNodes[0];
      //this.el.nativeElement.disabled = true;
      //this.el.nativeElement.disabled = 'disabled';
      //this._renderer.setProperty(rootElem, 'disabled', true);

      this._renderer.setProperty(rootElem, 'disabled', 'disabled');

//      this.viewContainer.clear();
    }
  }

}

For example this button icon is what I am trying to disable.

<button mat-icon-button class="action--icon" matTooltip="Notes" matTooltipPosition="above" (click)="openNotesDialog(element.earningsFileId)" *appIsGranted="['EARNINGS', 'viewearnings']">
  <mat-icon>chat</mat-icon>
</button>

The idea would be that this would work across all material items by just adding the attribute disabled to all material components.

1
Instead of adding directive for disabled why not use property binding for that element like this [disabled]="yourCondition()" ? - Indrajeet
@Indrajeet - If you use a directive you can apply it to a any element. See angular.io/guide/attribute-directives. It's a good way to provide reusable custom behavior for DOM elements. - DaggeJ
yes but usually disabled is available to every element right - Indrajeet
As long as you are creating directive for disabled, that can be avoided. if the use case is different for example adding asterisk to make it look like required, it makes a lot of sense to use directive. don't you think? - Indrajeet
@Indrajeet disabled attribute is not avilable for all elements. check this:w3schools.com/tags/att_disabled.asp - Chellappan வ

1 Answers

0
votes

We are doing something similar in our app through a directive that gets passed a list of roles required for running the actions associated with the element it is set on.

It works by using JQuery's method attr to set disabled and other attributes.

The directive;

@Directive({
    selector: '[appEditEntityActions]'
})
export class EditEntityActionsDirective implements OnInit {
    @Input() requiresAnyRole: string[] = null;

    constructor(
        private authorizationService: AuthorizationService,
        private element: ElementRef) { }

    ngOnInit() {
        var userCanEdit = this.authorizationService.hasAnyClaim(this.requiresAnyRole);
        if (!userCanEdit) {
            this.turnOffElement();
        }
    }

    private turnOffElement(): void {
        var jqElem = $(this.element.nativeElement);

        jqElem.off();
        jqElem.find('*').off();

        // app-opac-50-disabled-cursor-not-authorized is a css class that sets cursor, transparency etc...
        jqElem
            .attr('disabled', 'disabled')
            .attr('href', '')
            .addClass('app-opac-50-disabled-cursor-not-authorized')
            .attr('title', 'Not authorized');

        jqElem
            .find('button')
            .addClass('text-muted')
            .attr('disabled', 'disabled');

        jqElem.find('a')
            .attr('href', '')
            .addClass('app-opac-50-disabled-cursor-not-authorized');

        jqElem.on('click', (e: Event) => {
            e.preventDefault();
        });
    }
}

Usage;

<button appEditEntityActions [requiresAnyRole]='["Viewer", "Editor"]' (click)="doSomething();">Sample button</button>

Hope it helps you.