Search code examples
javascriptangulartypescriptangular6angular2-directives

not show <ng-template> when using structure directive


i create this directive fot show or hidde label .

   Directive({
  selector: '[appUser]'
})
export class UserDirective {

  RoleId:Subscription | null=null;
  op:boolean;
  _roleId:number;
  opo:ValidateUR;

  constructor(private optService:OptionsService
    ,private logserve:LoginService,
    private templateRef: TemplateRef<any>,
    private viewContainerRef: ViewContainerRef) { 
     this.opo=this.optService.initialValidateUR();
      this.RoleId=this.logserve._roleId$.subscribe((rId)=>{
      this._roleId=rId;
    })
  }

  @Input('appUser') set ngRoleValidate(oId:number)
  {
    this.opo.optionId=oId;
    this.optService.ValidateUser(this.opo).subscribe((rid)=>{

      if(rid==true)
      {
        console.log('in true')
          this.viewContainerRef.createEmbeddedView(this.templateRef);
      }else{
          this.viewContainerRef.clear();
      }
    })
  }
}

and this is html code :

   <li *ngFor="let op of optionList">
        <ng-template *appUser="op.id">
              <!-- <fa-icon [icon]="op.icon"></fa-icon>  -->
              <label  (click)='this[op.routeFunctionName]()'>{{op.optionName}}</label>
        </ng-template>
    </li>

now i need when rid is true , it show label and when it false it hidde label but when rid is true it not show me label . whats the problem ?


Solution

  • The part of the template:

    <ng-template *appUser="op.id">
    

    is expanded to:

    <ng-template [appUser]="op.id">
      <ng-template>
    

    Your directive renders all what is located inside <ng-template [appUser]="op.id">. And we can see it's wrapped into another ng-template that can't be rendered without creating embedded view.

    In order to render it correctly I would use ng-container instead of ng-template:

    <ng-container *appUser="op.id">
      <!-- <fa-icon [icon]="op.icon"></fa-icon>  -->
      <label  (click)='this[op.routeFunctionName]()'>{{op.optionName}}</label>
    </ng-container>
    

    Another way is using expanded version :

    <ng-template [appUser]="op.id">
      <!-- <fa-icon [icon]="op.icon"></fa-icon>  -->
      <label  (click)='this[op.routeFunctionName]()'>{{op.optionName}}</label>
    </ng-template>