0
votes

I'm trying to create a custom directive for disabling a form field but it's not working.

import { Directive, Input, ElementRef, Renderer2 } from '@angular/core';

@Directive({
  selector: '[appCustomDisable]',
  })
 export class CustomDisableDirective {
@Input() appCustomDisable: boolean;
constructor(private el: ElementRef, private renderer: Renderer2) {}

ngOnChanges() {
if (this.appCustomDisable) {
  this.renderer.setProperty(this.el.nativeElement, 'disabled', 
this.appCustomDisable);
} else {
  this.renderer.setProperty(this.el.nativeElement, 'disabled', 
this.appCustomDisable);
 }
}
}

I also tried the above using Render from '@angular/core'

 this.renderer.setElementAttribute(this.el.nativeElement, 'disabled', 
'true');

in app.component.html I'm using like [appCustomDisable]="myVar"

Stackblitz link https://stackblitz.com/edit/angular-lxb661

2
What kind of element are you placing the directive on? Have you added styles to the element which apply when it's disabled? How do you know it's not working? - Christian
And what's wrong with just [disabled]="someBoolean" which doesn't need any custom directive? - JB Nizet
Nvm, I can see you're trying to disable a material form control that way. What you're doing is incorrect, as the Material team have already implemented the logic of being able to disable their controls. Look into FormsModule or ReactiveFormsModule and how to disable controls respectively. - Christian
I provided u the stackbliz link. U can get everything from that. I know its not working bcoz the form is not getting disabled. - Anil Kumar Reddy A
I know how to use [disabled]="someBoolean", but i want a custom directive for that where i want to implement some complex functions inside it - Anil Kumar Reddy A

2 Answers

1
votes

Apparently, what you want to disable is the MatInput directive that is present on the same element. So, just inject it into your component, and disable it:

import { Directive, Input } from '@angular/core';
import { MatInput } from '@angular/material';

@Directive({
  selector: '[appCustomDisable]'
})
export class CustomDisableDirective {

    @Input() appCustomDisable : boolean;
    constructor(private matInput: MatInput) {}

    ngOnChanges() {
        this.matInput.disabled = this.appCustomDisable;
    }

}

Demo

1
votes

Since your are using MatInput your Code wont work for that. But you can adapt it simply like:

import { Directive, ElementRef, Input, Renderer2, Optional, S } from '@angular/core';
import { MatInput } from '@angular/material'

@Directive({
  selector: '[appCustomDisable]'
})
export class CustomDisableDirective {
  @Input() appCustomDisable: string;
  constructor(@Optional() private matInput: MatInput, private el: ElementRef, private renderer: Renderer2) { }

  ngOnChanges() {
    // Find Input
    let input: any;
    if (this.matInput) {
      // It's a Material Input
      input = this.matInput;
    }
    else {
      // Its a native Input
      if (this.el.nativeElement && this.el.nativeElement.tagName && this.el.nativeElement.tagName === "INPUT") {
        input = this.el.nativeElement;
      } else {
      // No Input found
      // return or throw error
      return;
      }
    }

    if (this.appCustomDisable === 'hide') {
      this.renderer.setStyle(this.el.nativeElement, 'display', 'none')
    } else if (this.appCustomDisable === 'view') {
     console.log(input);
     input.disabled = true;
    }
    else {
      this.renderer.setStyle(this.el.nativeElement, 'display', 'block')
    }
  }

}