72

I have an implementation where parent wants to pass certain data to child component via the use of @Input parameter available at the child component. However, this data transfer is a optional thing and the parent may or may not pass it as per the requirement. Is it possible to have optional input parameters in a component. I have described a scenario below:

 <parent>
    <child [showName]="true"></child> //passing parameter
    <child></child> //not willing to passing any parameter
</parent>



//child component definition
@Component {
    selector:'app-child',
    template:`<h1>Hi Children!</h1>
          <span *ngIf="showName">Alex!</span>`
}


export class child {

    @Input showName: boolean;

    constructor() { }

}
Sumit Agarwal
  • 4,091
  • 8
  • 33
  • 49

3 Answers3

134

You can use the ( ? ) operator as below

import {Component,Input} from '@angular/core';
@Component({
    selector:'child',
    template:`<h1>Hi Children!</h1>
          <span *ngIf="showName">Alex!</span>`
})


export class ChildComponent {

    @Input() showName?: boolean;

    constructor() { }

}

The parent component that uses the child component will be as

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
      <child [showName]="true"></child>
      <child ></child>
    </div>
  `,
})
export class App {
  name:string;
  constructor() {
    this.name = 'Angular2'
  }
}

LIVE DEMO

Aravind
  • 40,391
  • 16
  • 91
  • 110
  • 12
    This should be the answer. Also works with default values `@Input() showName?: boolean = true;` – Matthias Tylkowski Mar 22 '17 at 16:04
  • 3
    I was wondering , is there any difference vs the regular `@Input() showName: boolean;` ? and then check if not null ? I mean - what is the difference ? – Royi Namir Feb 09 '18 at 08:01
  • 1
    @RoyiNamir Most importantly I would say, it is a form of documentation. By placing the ? or not you can communicate whether your component can deal with this input being undefined or not. Also, I think it is recognized by the strictNullChecks compiler option https://christianliebel.com/2017/05/angular-typescript-writing-safer-code-with-strictnullchecks/ – masterxilo Apr 05 '19 at 11:11
  • 1
    @MatthiasTylkowski if you set a default value then it doesn't make sense to make it optional, since it will always be set to something. – rooby May 31 '19 at 07:38
  • @rooby Optional does not mean it has to be null. It always depends on the context. – Matthias Tylkowski Jun 02 '19 at 08:29
  • 1
    @MatthiasTylkowski Optional means that showName property might possibly not exist, yet setting it to true by default means it will always exist, so there's no point making it optional. (null is irrelevant here, a property set to null still exists. optional only relates to defined or undefined.) - optional here doesn't refer to whether or not the input has to be passed in (inputs are optional by default) but whether the property showName has to exist on the class. – rooby Jun 05 '19 at 14:09
33

Input values are optional by default. Your code will fail only when it tries to access properties of inputs that are not actually passed (since those inputs are undefined).

You can implement OnChanges or make the input a setter instead of a property to get your code executed when a value is actually passed.

export class child {

    @Input set showName(value: boolean) {
      this._showName = value;
      doSomethingWhenShowNameIsPassed(value);
    }

    constructor() { }
}
Arnaud P
  • 12,022
  • 7
  • 56
  • 67
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Check @galvan's comment, it seems to be a better solution. – Sumit Agarwal Sep 27 '16 at 06:51
  • 7
    Why do you think it's better? When the parent has to make a request to the server and only then passes the value to the child, then this might be quite some time after `ngAfterViewInit()` was called. `ngAfterViewInit()` might work in your concrete case but in general I wouldn't recommend it. – Günter Zöchbauer Sep 27 '16 at 06:53
  • You mean to say, If I am changing the values on the fly on client side? And as explained by you, should i call the setter method in the child directive? – Sumit Agarwal Sep 27 '16 at 07:00
  • 1
    You don't need to call the setter but if you have `` and `propOnParent` is initialized after some async call completes, then Angular updates the `showName` input in `` or in case when it's a setter, calls the setter with the updated value. – Günter Zöchbauer Sep 27 '16 at 07:03
  • Also if you just care about statically bound valus like `true` in your question, `ngOnInit()` is the more common lifecycle hook than `ngAfterViewChecked()`. – Günter Zöchbauer Sep 27 '16 at 07:05
  • Tip: If you create a setter without a getter, Typescript will still allow you to call the getter but will return undefined. If you need the value you must add `get showName() { retrun this._showName; }`. This is just the way Typescript / Javascript works unfortunately! – Simon_Weaver Jul 16 '22 at 22:38
1

You have two options here.

1) You can use an *ngIf on the child in case the child does not need to be displayed when its Input is empty.

 <parent>
    <child *ngIf="true" [showName]="true"></child> //passing parameter
    <child></child> //not willing to passing any parameter
</parent>

2) In case the child should get displayed without any input, you can use a modified setter to check for the presence of input variables`

In the child.ts:

private _optionalObject: any;
@Input()
set optionalObject(optionalObject: any) {
    if(optionalObject) this._optionalObject = optionalObject;
}
get optionalObject() { return this._optionalObject; }
Alexander Ciesielski
  • 10,506
  • 5
  • 45
  • 66