0

I am trying to create a dynamic select component for my application. This component would be used in various forms throughout my application. In some cases, there may be some predefined value that may be provided to the select, in which case the value would be selected as default by the drop-down. In order to achieve this functionality I have looked over SO and found various questions that answer this problem, but are using NgModule as a directive for adding default value, whereas I am using formControlName for my component. I have tried a solution myself (code added below) but it doesn't seem to be working. I am reluctant to use ngModule with formControlName because the feature is deprecated in Angular 6 (the version I am using). How do I achieve the functionality?

component.html

<div [formGroup]="group">
  <select id="{{ id }}" formControlName="{{ formControlName }}" class="form-control">
      <option value="" disabled selected>{{placeholder}}</option>
      <option *ngFor="let item of data" [ngValue]="item.id">{{item.name}}</option>
  </select>
</div>

component.ts

import { Component, ViewEncapsulation, Input } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';

@Component({
  selector: 'app-dropdown',
  templateUrl: './dropdown.component.html',
  styleUrls: ['./dropdown.component.scss'],
  encapsulation: ViewEncapsulation.None
})
/**
* This class is used to create a generic dropdown component. Population is done on runtime
*/
export class DropdownComponent{
  /**
  * Define FormGroup
  */
  @Input() group: FormGroup;

  /**
  * Define formControlName
  */
  @Input() formControlName: string;

  /**
  * Define id
  */
  @Input() id: string;

  /**
  * Define data
  */
  @Input() data: any;

  /**
  * Define placeholder
  */
  @Input() placeholder: string;

  /**
  * For any predefined value being passed
  */
  @Input() predefined: string;

  constructor() { }

}

what I tried (ts file remained the same)

<div [formGroup]="group">
  <select id="{{ id }}" formControlName="{{ formControlName }}" class="form-control">
    <ng-template *ngIf="predefined !== undefined; else default">
      <option *ngFor="let item of data" [selected]="item.id === predefined">{{item.name}}</option>
    </ng-template>
    <ng-template #default>
      <option value="" disabled selected>{{placeholder}}</option>
      <option *ngFor="let item of data" [ngValue]="item.id">{{item.name}}</option>
    </ng-template>
  </select>
</div>
Muhammad Hamza
  • 823
  • 1
  • 17
  • 42

2 Answers2

0

In order to cater the problem, the solution was to define a method in the OnInit lifecycle hook, which extracted the entire object an inserted into the template. The lifecycle hook sets a particular variable called selection and sets to the formControl:

selection: any

ngOnInit() {
    if (this.predefined !== undefined) {
      let index = Object.keys(this.data);
      var self = this;
      index.forEach(function(i) {
        Object.keys(self.data[i]).some(function(k) {
          if (self.data[i][k] === self.predefined) {
            self.selection = self.data[i];
            return self.data[i][k];
          }
        }
        )
      });
      this.group.controls[this.formControlName].setValue(this.selection.id, { onlySelf: true });
    }
  }

The template didn't need any modification like I did in the question's update, so reverted to the previous:

<div [formGroup]="group">
  <select id="{{ id }}" formControlName="{{ formControlName }}" class="form-control">
      <option value="" disabled selected>{{placeholder}}</option>
      <option *ngFor="let item of data" [(ngValue)]="item.id">{{item.name}}</option>
  </select>
</div>
Muhammad Hamza
  • 823
  • 1
  • 17
  • 42
-1

So if you want to provide any default values to the select statement you can do something like below,

Let's say I have this array of object in .ts

 Sports = [
 {
    "name": "running",
    "value" : "0"
 },
 {
    "name": "triathlon",
    "value" : "1"
 }
]

You can set the default value for the select statement in html like below,

<select class="form-control" (change)="get($event.target.value)">
   <option [value]="null" hidden>
      Select
   </option>
   <option *ngFor="let sport of Sports" [value]="sport.value">
      {{sport.name}}
   </option>
</select>