[Fixed] custom if directive does not show expected results

Issue

in this tutorial

https://www.sitepoint.com/practical-guide-angular-directives/

i am learning how to create a customised directive. i followed the steps as shown in the code posted below, but despite added the exact code as explained in the aforemenrtioned website, when i run the command

ng serve --open

i get something as shown in the image posted below.
please let me know why myCustomIf is not working. i say that myCustomIf is not working because what i got on the localhost:4200 is something as shown in the image posted

please let me know how to make the myCustomIf works as explained in the tutorial in the above posted link

app.component.ts:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'ngDirective1';
  name = 'Angular';
  condition = false;    

}

app.myCustomeIfDirective.ts:

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

@Directive({
    selector: '[myCustomIf]'
})
export class MyCustomeIfDirective{
    constructor(private templateRef: TemplateRef<any>,private viewContainer: ViewContainerRef){ }

    @Input()
    setMyCustomIf(condition : boolean) {
        if(condition) {
            this.viewContainer.createEmbeddedView(this.templateRef);
        } else {
            this.viewContainer.clear();
        }
    }
}

app.module:

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

@Directive({
    selector: '[myCustomIf]'
})
export class MyCustomeIfDirective{
    constructor(private templateRef: TemplateRef<any>,private viewContainer: ViewContainerRef){ }

    @Input()
    setMyCustomIf(condition : boolean) {
        if(condition) {
            this.viewContainer.createEmbeddedView(this.templateRef);
        } else {
            this.viewContainer.clear();
        }
    }
}

app.component.html:

<h1 my-error>Hello {{name}}</h1>
<h2 *myCustomIf="condition">Hello {{name}}</h2>
<button (click)="condition = !condition">Click</button>

image:

enter image description here

Solution

If you open console it should show smth like:

NG0303: Can’t bind to ‘myCustomIf’ since it isn’t a known property of
‘h2’

An Angular structural directive, that is written in a short syntax(with *) and that takes one input or more inputs, must have an @Input with the same name as directive’s attribute selector(other inputs follow another rule described here What is the exact grammar for Angulars structural directives), e.g.:

@Directive({
    selector: '[anyAttr]'
})
export class MyCustomeIfDirective{
    @Input()
    anyAttr: any;

or

@Directive({
    selector: '[anotherAttr]'
})
export class MyCustomeIfDirective{
    @Input()
    set anotherAttr(val: any) {}

Why is it so?

That’s because *ngIf is just a shortcut for expanded version:

<ng-template [ngIf]="...">...

or

*anyAttr => <ng-template [anyAttr]="...">...

Now, let’s look at your code:

@Directive({
    selector: '[myCustomIf]'
})
export class MyCustomeIfDirective{
    @Input()
    setMyCustomIf(condition : boolean) {

Several things to notice:

  • setMyCustomIf is just a method in your case
  • if you convert it to a setter set MyCustomIf then MyCustomIf doesnt match myCustomIf because js is case-sensitive.

The solution is:

@Input()
set myCustomIf(condition : boolean) {

Ng-run Example

Leave a Reply

(*) Required, Your email will not be published