Instruction to deactivate elements and eliminate additional properties that are marked as [disabled]

I'm encountering a puzzling issue. A directive needs to be implemented that enables or disables UI elements based on the user's role. While it works for UI elements that are not disabled by any other conditions, some buttons become disabled when just one of multiple conditions is met. These conditions can change as the user interacts with the page.

// Directive
@Directive({
  selector: '[roleDisable]',
})
export class RoleDisableDirective implements OnInit, OnChanges {
  @Input('roleDisable') role: string;
  @HostBinding('disabled') disabled: string;

  constructor(
    private store: Store<fromApp.AppState>, 
    private elementRef: ElementRef, 
    private renderer: Renderer2
  ) {}

  ngOnInit() {
    this.checkRights();
  }

  ngOnChanges() {
    this.checkRights();
  }

  private checkRights(): void {
    this.store.select(fromClient.hasNeededRole, {role: this.role }) //Observable<string>
      .pipe(take(1))
      .subscribe(hasRole => {
        // Attempted to remove [disabled], but does not work
        if (element.hasAttribute('disabled')) {
          this.renderer.removeAttribute(element, 'disabled');
        }
        this.disabled = hasRole; // this works
     });
  }
}

// Usage in component template
<button
  roleDisable="start_process"
  mat-raised-button
  (click)="startProcess()"
  [disabled]="
    !processEnabled ||
    isUnavailable ||
    hasInputs ||
    preparationRunning ||
  "
>

If I remove the [disabled] property with all the conditions, the button becomes disabled, indicating that the directive is functioning correctly. However, keeping the [disabled] calculation and having no condition evaluate to true results in the directive being overridden and the button becoming enabled, which is not the intended behavior.

How can I ensure that the directive successfully overrides/removes the [disabled] property calculation? Attempts to delete [disabled] before re-enabling it had no effect. Any suggestions?

Answer №1

Implement MatButton class into the RoleDisableDirective directive to access the mat-raised-btn element, allowing you to customize the disabled property of MatButton within the directive code.

directive.ts

import { MatButton } from '@angular/material/button';

@Directive({
  selector: '[roleDisable]',
})
export class RoleDisableDirective implements OnInit, OnChanges {
  @Input('roleDisable') role: string;

  constructor(
    private store: Store<fromApp.AppState>,
    private matBtn:MatButton
  ) {}

  ngOnInit() {
    this.checkRights();
  }

  ngOnChanges() {
    this.checkRights();
  }

  private checkRights(): void {
    this.store.select(fromClient.hasNeededRole, {role: this.role }) //Observable<string>
      .pipe(take(1))
      .subscribe(hasRole => {
        this.matBtn.disabled = true;
     });
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Importing modules that export other modules in Typescript

I am facing an issue with two modules and two classes. ModuleA, ModuleB, ClassA, and ClassB are defined as follows: export class ClassA { } export class ClassB { } The modules are structured like this: export * from './ClassA'; export module ...

Creating consistency in tab spacing within a text area

At the moment, I am utilizing an HTML textarea attribute to collect input from users and then displaying that text back to them formatted. However, there seems to be an issue with how it handles tabs. For instance, when attempting to input the following: ...

Show varying mat-options based on the selected value of another mat-select

When selecting a continent from the first mat-select, only the countries belonging to that continent should appear in the second mat-select options. For example, if Asia is chosen as the continent, only Asian countries should be displayed. <div class=&q ...

Exploring the capabilities of Angular2 and Jasmine through testing

I have been working on a basic spec for a component and I'm curious about the test's behavior. The test is designed to verify if a component is successfully created. It seems that when the test is executed, it first compiles and runs the Compone ...

Proper format for implementing recursive API call in React using Redux-Thunk

Our goal is to create a recursive API call based on the number of records returned in the response. For instance, if the response contains 10 records out of a total of 20, we should make another API call for the next 10 records. What is the best approach ...

What are the steps to properly build and implement a buffer for socket communication?

I have encountered an issue while converting a code snippet to TypeScript, specifically with the use of a Buffer in conjunction with a UDP socket. The original code fragment is as follows: /// <reference path="../node_modules/DefinitelyTyped/node/node ...

Let's compare the usage of JavaScript's toUTCString() method with the concept of UTC date

When I fetch the expiry date time in UTC from the Authentication API along with a token, I use the npm jwt-decode package to extract the information. private setToken(value: string) { this._token = value; var decoded = jwt_decode(value); this._ ...

The ngTemplateOutletContext context source is not defined

That snippet of code was functional with Angular 2, and possibly even with versions earlier than Angular 4.3.6. Currently, the gradingKey object is undefined within the display or edit template section. However, it is not undefined in the getTemplate(gra ...

iOS Safari browser allows HTML5 video to be displayed over all other elements

I am currently developing an application that utilizes html5 video elements. When using playsinline to ensure the video is treated as an inline element for positioning on iOS Safari, everything seems to work as expected except for one issue - the video a ...

Error in VueJS/Typescript: Module 'my-module' or its type declarations are not found

Hey fellow developers! I'm currently working on a Vue2 setup with Nuxt and Typescript. I'm facing an issue while trying to install the awesome vue-slick-carousel module via yarn. When attempting to import the module in my component, Typescript th ...

Styling multiple checkbox items in an Angular Material Autocomplete

Is there a way to adjust the height of autocomplete multiple checkbox items in Angular Material? I'd like it to look like this With a line item height of 18px But instead, it looks like this when using multiple checkboxes With a different checkbox ...

Why bother specifying types when extending tsconfig?

Having an angular app that utilizes @types and custom typings, I am facing an issue where the app works when served but encounters errors during testing with ng test. It is puzzling to me why this discrepancy exists, and I am struggling to comprehend the r ...

What could be causing my "Swiper" component to malfunction in a TypeScript React project?

In my React project, I decided to incorporate the Swiper library. With multiple movie elements that I want to swipe through, I began by importing it as follows: import Swiper from 'react-id-swiper'; Utilizing it in my code like this: <div cla ...

I am facing an issue with Adal.service.ts in Angular while running tests using Jest, it's not working as expected

Can someone help me, please? I'm in the process of migrating to Jest for running unit tests on Angular. However, when I try to execute the tests, I encounter the following error: FAIL src/app/modules/dashboard/components/navbar/navbar.component.spec. ...

Using forkJoin() to introduce a delay between asynchronous API calls

Here is the code snippet I am currently working with: return forkJoin( pages.map( i => this.http.get(`devices?page=${i}&size=8000`) ) ).subscribe((event: any) => { event.forEach((entry) => { ...

Resolving the Duplicate Identifier Issue in Ionic 2 with Firebase Integration

I'm struggling with setting up ionic2 + Firebase 3. Following a tutorial, I installed Firebase and Typings using the commands below: npm install firebase --save npm install -g typings typings install --save firebase However, when I try to run ioni ...

Understanding Typings in Typescript

Just delving into the world of Angular2 and finding it quite exciting, but running into a roadblock with Typings. The concept is not clear to me - how do I utilize them and what purpose do they serve? Different sources suggest different approaches, some me ...

The Angular 2.0 HTTP post request encountered an error when trying to respond with a status of 200 Ok for a null

I'm currently attempting to post data using http in Angular 2. I have added an http call with the corresponding API, and when I click the button, it should send data to my database. However, an error is showing up in the console. XMLHttpRequest canno ...

Is it possible to navigate to the Angular component that defines a tag in VSCode by simply clicking on the tag?

In my current Angular project in VSCode, I often find myself wanting to delve deeper into specific tags that I encounter while coding. For instance, if I stumble upon a tag like <display-active-users>, I usually have to go through the process of sea ...

In Angular, use the ngFor directive to iterate through items in a collection and add a character to each item except

Currently, I am iterating through my data list and displaying it in the view using spans: <span *ngFor="let d of myData"> {{d.name}}, </span> As shown above, I am adding a comma ',' at the end of each item to ensure a coherent displ ...