Search code examples
angularangular-structural-directive

Micro syntax `as` not working with my own directive


I want to support the following micro syntax:

foo$ | async as xyz

Example:

<p *appVar="foo$ | async as xyz">
   Value is {{ xyz }}!
</p>

That stream is defined as

$foo = of('some value')

Here is my directive:

@Directive({
   selector: '[appVar]'
})
export class VarDirective<T> {
   @Input() appVar: T;

   constructor(
      private templateRef: TemplateRef<T>,
      private viewContainer: ViewContainerRef
   ) {}

   ngOnInit(): void {
      this.viewContainer.createEmbeddedView(this.templateRef);
   }
}

DEMO

Now, whatever I do, that xyz variable is always undefined.

If I create a context (which is suggested in this post)

 const context = { $implicit: this.appVar };
 this.viewContainer.createEmbeddedView(this.templateRef, context);

DEMO

I get the same result. Any suggestions what I do wrong here?


Solution

  • The expression has to be available in the context under the same name as the directive itself, which is appVar in this case:

    this.viewContainer.createEmbeddedView(this.templateRef, {
      $implicit: this.appVar,
      appVar: this.appVar
    });
    

    Demo

    Compare it to the built-in ngIf directive:

    @Input()
    set ngIf(condition: any) {
      this._context.$implicit = this._context.ngIf = condition;
      this._updateView();
    }
    

    and to the TuiLetContext:

    get $implicit(): T {
      return this.internalDirectiveInstance.tuiLet;
    }
    
    get tuiLet(): T {
      return this.internalDirectiveInstance.tuiLet;
    }