Search code examples
angularangular-directive

Angular Structural Directive with multiple parameters


I can't get a structural directive to work with multiple parameters.


This code works, the two parameters are logged, but it's not a structural directive:

import { Input, Directive, AfterViewInit } from "@angular/core";
import { ProfileModel } from "../auth/auth.models";

@Directive({
    selector: 'hasRole'
})
export class HasRoleDirective implements AfterViewInit {

    @Input()
    public profile: ProfileModel;

    @Input()
    public roleName: string;

    ngAfterViewInit(): void {
        console.log(this.roleName, this.profile);
    }
}

with this markup:

<hasRole [roleName]="'Admini'" [profile]="profile">A</hasRole>

But this code doesn't work, i.e. when I switch to a structural directive, the value in AfterViewInit are missing:

import { Input, Directive, AfterViewInit, ViewContainerRef, TemplateRef } from "@angular/core";
import { ProfileModel } from "../auth/auth.models";

@Directive({
    selector: '[hasRole]'
})
export class HasRoleDirective implements AfterViewInit {

    @Input()
    public profile: ProfileModel;

    @Input()
    public roleName: string;

    constructor(
        private view: ViewContainerRef,
        private templateRef: TemplateRef<any>,
    ) {
    }

    ngAfterViewInit(): void {
        console.log(this.roleName, this.profile);

        //if (this.profile.roles.find(o => o === this.roleName)) {
        //    this.viewContainer.createEmbeddedView(this.templateRef);
        //} else {
        //    this.viewContainer.clear();
        //}
    }
}

with this markup:

<div *hasRole [roleName]="'Admini'" [profile]="profile">A</div>

Solution

  • In structural directive you cannot use brackets for your inputs. And also it's better when your first input has the same name as Directive (hasRole)

    Your markup should look like this:

    <div *hasRole="'Admini';profile:'profile'"></div>
    

    Your @Inputs would then be:

    @Input()
    public hasRole: string;
    
    @Input()
    public hasRoleProfile: ProfileModel;
    

    Or you can use template

    <template [hasRole]="hasRole" [profile]="'profile'">
      </div></div>
    </template>