1

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.

9
  • Instead of adding directive for disabled why not use property binding for that element like this [disabled]="yourCondition()" ? Commented Apr 15, 2020 at 9:07
  • @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. Commented Apr 15, 2020 at 9:19
  • yes but usually disabled is available to every element right Commented Apr 15, 2020 at 9:19
  • 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? Commented Apr 15, 2020 at 9:21
  • @Indrajeet disabled attribute is not avilable for all elements. check this:w3schools.com/tags/att_disabled.asp Commented Apr 15, 2020 at 9:38

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

was using jquery the only way you got this to work?
@JeremyLove - never tried without JQuery. This article suggests some ways to do it with "pure" angular code; stackoverflow.com/questions/42261962/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.