Search code examples
angularangularjs-directive

Angular structural directive with multiple inputs has no value during first loading component


I have created a structured directive that takes multiple values. The issue I have is the second parameter which I add, is not being taking into consideration in the accessControllRole @Input. But the value is present in its own parameter declaration. Any idea what is going on and how can I get the value in the first @Input i.e. accessControlRole.

Here is the code.

@Directive({
  selector: '[accessControlRole]'
})
export class AccessControlRoleDirective implements OnInit {
  userProfile!: UserProfile;
  private _accessControlRolePermission!:string;

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainerRef: ViewContainerRef,
    private jwtAuthService: JwtAuthService,
    ) {
  }

  ngOnInit(): void {
  }

  @Input() set accessControlRole(roleAllowed: Permission[]) {
    this.jwtAuthService.user.subscribe(user => {
      if (user&&this._accessControlRolePermission) {
        this.userProfile = user;
        if(this._accessControlRolePermission === 'Approve'){
          console.log('yesssssssssssssssssssssss');
          this.viewContainerRef.createEmbeddedView(this.templateRef);
        }
      }
      else{
        console.log("_accessControlRolePermission value is empty");
      }
    });
  }

  @Input() set accessControlRolePermission(permission:string) {
    this._accessControlRolePermission = permission;
    console.log('accessControlRolePermission value::::',this._accessControlRolePermission);
  }
}

component class, I call directive like so,

<ng-container *accessControlRole="this.userPermissionRoles;permission:'Approve'">
         <a class="btn btn-lg btn-success btn-block">Approve</a>
</ng-container>

In the console I see this output

Directive value is empty

accessControlRolePermission value:::: Approve


Solution

  • Please move the template rendering code and just set the values, in the setter method, please find below working example! If you get ExpressionChangedAfterItHasBeenCheckedError please move the code into ngAfterViewInit instead of ngOnInit.

    import { CommonModule } from '@angular/common';
    import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
    
    @Directive({
      selector: '[accessControlRole]',
      standalone: true,
    })
    export class AccessControlRoleDirective {
      userProfile!: any;
      private _accessControlRolePermission!: string;
      private roleAllowed: any = [];
    
      constructor(
        private templateRef: TemplateRef<any>,
        private viewContainerRef: ViewContainerRef,
        private jwtAuthService: JwtAuthService,
      ) { }
    
      ngOnInit(): void {
        this.jwtAuthService.user.subscribe(user => {
          if (user && this._accessControlRolePermission) {
            this.userProfile = user;
            if (this._accessControlRolePermission === 'Approve') {
              console.log('yesssssssssssssssssssssss');
              this.viewContainerRef.createEmbeddedView(this.templateRef);
            }
          }
          else {
            console.log("_accessControlRolePermission value is empty");
          }
        });
      }
    
      @Input() set accessControlRolePermission(permission: string) {
        this._accessControlRolePermission = permission;
        console.log(
          'accessControlRolePermission value::::',
          this._accessControlRolePermission
        );
      }
    
      @Input() set accessControlRole(roleAllowed: any[]) {
        this.roleAllowed = roleAllowed;
      }
    }
    

    stackblitz