Angular: How to Get Default @Input Value

How to set default values for Angular 2 component properties?

That is interesting subject.
You can play around with two lifecycle hooks to figure out how it works: ngOnChanges and ngOnInit.

Basically when you set default value to Input that's mean it will be used only in case there will be no value coming on that component.
And the interesting part it will be changed before component will be initialized.

Let's say we have such components with two lifecycle hooks and one property coming from input.

@Component({
selector: 'cmp',
})
export class Login implements OnChanges, OnInit {
@Input() property: string = 'default';

ngOnChanges(changes) {
console.log('Changed', changes.property.currentValue, changes.property.previousValue);
}

ngOnInit() {
console.log('Init', this.property);
}

}

Situation 1

Component included in html without defined property value

As result we will see in console:
Init default

That's mean onChange was not triggered. Init was triggered and property value is default as expected.

Situation 2

Component included in html with setted property <cmp [property]="'new value'"></cmp>

As result we will see in console:

Changed new value Object {}

Init new value

And this one is interesting. Firstly was triggered onChange hook, which setted property to new value, and previous value was empty object! And only after that onInit hook was triggered with new value of property.

Angular: How to get default @Input value?

There is no standard angular way, because many times you would want null or undefined as value. Your ideas are not bad solutions. I got a couple more

  1. I suppose you can also use the ngOnChanges hook for this:
    1. @Input()
      type: string = 'defaultType';

      ngOnChanges(changes: SimpleChanges): void {
      // == null to also match undefined
      if (this.type == null) {
      this.type = 'defaultType';
      }
      }

      1. Or using Observables:
        1. private readonly _type$ = new BehaviorSubject('defaultType');

          readonly type$ = this._type$.pipe(
          map((type) => type == null ? 'defaultType' : type)
          );

          @Input()
          set type(type: string) {
          this._type$.next(type);
          }

          1. Or create your own decorator playground
            1. function Default(value: any) {
              return function(target: any, key: string | symbol) {
              const valueAccessor = '__' + key.toString() + '__';

              Object.defineProperty(target, key, {
              get: function () {
              return this[valueAccessor] != null ? this[valueAccessor] : value
              },
              set: function (next) {
              if (!Object.prototype.hasOwnProperty.call(this, valueAccessor)) {
              Object.defineProperty(this, valueAccessor, {
              writable: true,
              enumerable: false
              });
              }

              this[valueAccessor] = next;
              },
              enumerable: true
              });
              };
              }

              which you can use like this:

              @Input()
              @Default('defaultType')
              type!: string;

              How to set default value for Input Angular?

              Hai you can try to set the value in ngOnInit. once the ngOnInIt is called the value for the
              applicant will be set if any provided by the parent component.

              Here check if the value is undefined and if so set a default

              @Input() applicant: Applicant;

              ngOnInIt() {
              if (!this.applicant) {
              this.applicant = {
              // ur defaults here
              };
              }

              if you want to always pass proper values to children components from parent then

              this.applicants.map((applicant) => {
              if (!applicant || !applicant.representative) {
              applicant = {
              // your defaults here
              };
              this.representativeAdapter.adapt(applicant.representative);
              ...

              How to set default parameter for @Input in Angular2?

              try

              @Input() name: string = 'noname';

              Angular setting a default number value

              No need for value="1". Just in your .ts do this:

              ngOnInit() {
              WorkItemSelection.CopyQuantity = 1;
              }

              Not able to set default value of input (Angular)

              You are using FormBuilder and as such the value property of input is not used. The initial value is initialized by the FormControl

              Remove the following from the constructor

              this.updateForm = this.formBuilder.group({
              nomeUpdate: this.formBuilder.control("")
              })

              Modify getCliente()

              getCliente(){
              this.userService.getUser(localStorage.getItem('userAtual'))
              .pipe(first()).subscribe(user => {
              this.cliente = user[0];
              this.updateForm = this.formBuilder.group({
              nomeUpdate: this.formBuilder.control(this.cliente.nome)
              })
              });
              }

              Have added .pipe(first()) so only first value received is used.

              Hope it helps!

              (ngModel)] input with default input values

              <input [(ngModel)]="message.name" name="name" class="input" type="text" required>

              In your component :

              message : any = { name: 'YOUR_DEFAULT_VALUE', }

              Angular: Setting an emptied string to a default value does not update the bound text field properly if the field previously had the default value

              Inherent error

              The ngModel directive uses @Input and @Output to obtain the value and emit the change event. So binding a function like setter or getter to a directive like [ngModel] with default change detection strategy would trigger the function for each change detection.

              To replicate this error, plug in a console.log in the getter, type some value and keep pressing backspace in the <input> and let go. You could see the console.log messages keeps getting printed.

              Error replication: Stackblitz



              Why isn't 'DEFAULT' inserted on Ctrl+a+Backspace

              As said before, the ngModel directive uses @Input and correspondingly the ngOnChanges() hook to fetch any changes to the value from <input> tag. One important thing to note is ngOnChanges() won't be triggered if the value hasn't changed(1).

              We could try to split the two-way binding [(ngModel)] to [ngModel] input and (ngModelChange) output.

              export class AppComponent {
              public testString: string;

              onChange(value: string) {
              this.testString = value === '' ? 'DEFAULT' : value;
              }
              }
              <input type="text" [ngModel]="testString" (ngModelChange)="onChange($event)" />

              Still error prone: Stackblitz

              Here the Ctrl+a+Backspace any string other than 'DEFAULT' would insert 'DEFAULT' as expected. But Ctrl+a+Backspace 'DEFAULT' would result in empty <input> box due the ngOnChanges() issue discussed above.



              Solution

              One way to achieve expected behavior is to not depend on the ngModel directive's ngOnChanges() hook to set the value, but to do it ourselves manually. For that we could use an Angular template reference variable in the <input> and send it to the component for further manipulation.

              export class AppComponent {
              public testString: string;

              public onChange(value: string, inputElem: HTMLInputElement) {
              this.testString = value === '' ? 'DEFAULT' : value;
              inputElem.value = this.testString;
              }
              }
              <input
              type="text"
              #myInput
              ngModel
              (ngModelChange)="onChange($event, myInput)"
              />

              Working example: Stackblitz

              Here the #myInput is the template reference variable. If this feels hacky, you'd need to know using ngModel to manipulate <input> is in itself called template driven forms. And it's quite legal to manipulate the template ref directly.

              With all that said, IMO in cases where such input manipulation is needed, I'd recommend you to use the Angular Reactive Forms instead. It provides a more granular control over the input.


              (1) The ngOnChanges() won't be triggered if the previousValue and currentValue of the respective @Input variable's SimpleChange object hasn't changed.

              Angular: How to set input to its default value

              What you need is reference to the form in order to have easier access to all controls within that form.

              For that reason I added reference to the form and ngSubmit.

              <form (ngSubmit)="adicionar(f)" #f="ngForm">
              ...
              </form>

              With this in your adicionar method within component class you have access to all values of the form along with access to resetForm method which resets form data along with touched and dirty flags.

              Another important is checks of errors and deciding when to show them. Usually you want to do that when form is submitted or field has been touched/dirty.

              Example:

              <small
              *ngIf="Tipo.invalid && (f.submitted || Tipo.touched || Tipo.dirty)"
              class="invalid-feedback">
              <span *ngIf="Tipo.errors.required">Tipo is required</span>
              </small>

              Supporting documentation
              https://angular.io/guide/form-validation#template-driven-validation

              Working StackBlitz -> https://stackblitz.com/edit/angular-nk6zga



              Related Topics



Leave a reply



Submit