1

Like I said, I want to use the existing structural directive string based syntax in custom directive

<element *ngFor='let x of array;let last = last;'></element>

I don't find any detailed docs, how we can decode the above syntax in our custom structural directive. I know we can use this syntax with all structural directive *xyz but I always use [xyz] instead. I try to find angular official docs but got nothing.

So I move into their code to understand *NgFor in github, and I got it all except how they are decoding the syntax.

If you see the selector it is like below

@Directive({selector: '[ngFor][ngForOf]'})

@Input()
set ngForTrackBy(fn: TrackByFunction<T>) {
    //definition
}

And all inputs method starts with selector prefix like ngForTrackBy. is it like this only? do we have to follow the selector prefix?
If Yes then what are all other things we can do with this prefix based approach? If no then what is the right approach?

1 Answer 1

5

It's the job of the compiler to match the variables defined with the let syntax and the context passed into the embedded view. You can define as many variables as you want, but if you don't pass the values for them through the context, their values will be undefined.

Here I'm using a custom my directive and defining two variables a and b with the let syntax:

<ng-template my let-a=a let-b=b let-c=c>
  <span>inside my, a is {{a}}, b is {{b}}, c is undefined: {{c === undefined}}</span>
</ng-template>

Then when describing the directive I pass the context with variable values to the embedded view:

import { Directive, TemplateRef, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[my]'
})
export class MyDirective {
  constructor(public vc: ViewContainerRef, public t: TemplateRef<any>) {
  }

  ngOnInit() {
    const t = this.vc.createEmbeddedView(this.t, {a: 3, b: 4});
  }
}

The same holds true for the ngForOf directive, here's how the context looks for it:

export class NgForOfContext<T, U extends NgIterable<T> = NgIterable<T>> {
  constructor(public $implicit: T, public ngForOf: U, public index: number, public count: number) {}

  get first(): boolean {
    return this.index === 0;
  }

  get last(): boolean {
    return this.index === this.count - 1;
  }

  get even(): boolean {
    return this.index % 2 === 0;
  }

  get odd(): boolean {
    return !this.even;
  }
}

You can also use a shorthand syntax with custom directive:

<span *my="let a=a; let b=b; let c=c;">inside my, a is {{a}}, b is {{b}}, c is undefined: {{c === undefined}}</span>
Sign up to request clarification or add additional context in comments.

6 Comments

Ok so we will write directive taking template in mind for using short hand syntax. One more thing to confirm - with ngForOf it looks like we must use prefix with directive inputs as compiler adding prefix while converting short hand syntax into ng-template. Ex: if I want of as input in directive then it would be myOf as input
not really, this will work too <span *my="let a=a; let b=b; let c=c;">inside my, a is {{a}}, b is {{b}}, c is undefined: {{c === undefined}}</span>. ngFor supports both names @Directive({selector: '[ngFor][ngForOf]'}) github.com/angular/angular/blob/…
Please correct me, let a=a; let b=b; let c=c; is assigning data from directive to the HTML, not the other way around. like if we need to pass data (array) inside directive as input using same syntax then we need prefix in method Name like incase of ngForOf, it is of and trackBy
<li *ngFor="let item of items; index as i; trackBy: trackByFn">...</li> converts into this <ng-template ngFor let-item [ngForOf]="items" let-i="index" [ngForTrackBy]="trackByFn"> <li> </li> </ng-template> right?
finally found this in docs, I think they update it recently The parser applies PascalCase to all directives and prefixes them with the directive's attribute name, such as ngFor. For example, the ngFor input properties, of and trackBy, map to ngForOf and ngForTrackBy. As the NgFor directive loops through the list, it sets and resets properties of its own context object. These properties can include, but aren't limited to, index, odd, and a special property named $implicit
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.