Search code examples
angularangular-directive

Angular: not getting reference of Form pristine/invalid status inside directive


I have a directive "hasPermission" which is being used inside a Component. Function of this directive is to check permission if not have then disable the button but the moment i make any change to form fields like some text added it enables the button again and that is happening due to [disabled] property which looking for forms pristine/invalid status.

How can i manage this ?

I want to first check for permissions if that is there then only this pristine/invalid comes into picture. Please guide.

If i get the status of this form's pristine/invalid inside directive I believe we can manage it but how to get it inside, i tried some solutions using DoCheck/Host etc none giving me Form reference inside Directive.

I don't want to use nativeElement (until some one says that is only way :))

enter image description here

Sample Code

   import {
    Directive,
    OnInit
} from '@angular/core';
import {
    NgForm
} from '@angular/forms';
@Directive({
    selector: '[haspermission]'
})
export class HaspermissionDirective implements OnInit {
    constructor() {
        ....
    }
    ngOnInit() {
        this.someService.getCurrentUser().subscribe(response => {
            this.store(response);
        });

    }

    store(data: IUser) {
        this.roles = JSON.parse(data.role);
        //.....doing some logic to calculate permissisons
        var hasPerm = this.roles.find(o => (o.RoleCode in permConfig.permission));
        if (!hasPerm) {
            this.element.nativeElement.disabled = true;
        }
    }
}

Solution

  • Use can use exportAs property on the Directive decorator.Which will expose appHaspermission Directive instance.

    The exportAs takes the name under which the component instance is exported in a template.

    appHaspermission.Directive.ts

    import { Directive, OnInit } from '@angular/core';
    import { NgForm } from '@angular/forms';
    @Directive({
      selector: '[appHaspermission]',
      exportAs: 'hasPermission'
    })
    export class HaspermissionDirective implements OnInit {
      hasPermission = false;
      constructor() {
    
      }
      ngOnInit() {
        this.hasPermission = true;
      }
    }
    

    Then create local variable on your button and assign in to exported hasPermission Directive so that you can access directive properties from template

    <form>
        <input type="text" ngModel name="name" >
     <button #ref="hasPermission" appHaspermission  [disabled]="ref['hasPermission'] && (client.pristine || something else)" >Enable</button>
    </form>
    

    Example:https://stackblitz.com/edit/angular-pebven