Search code examples
angularangular7

Select Form Control returns [object Object] in Angular 7


In my Angular 7 project, I have a reactive form with select and *ngFor blocks. ngFor values are filtered based selected value from the options and custom pipe takes care of filtering. Whenever I select a value from options, all I see is "[object Object]" output. I tried (ngModelChange)=fun(), change events. They did not work.

Form:

    <div class="container container-fluid">
      <h3 style="text-align: center"> BCMC CyberSecurity Jobs</h3>
      <form [formGroup]="jobsForm">
      <div class="row" style="margin-top: 40px">
        <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">
            <label> Job Type:
              <select class="custom-select" formControlName="jobTypeControl" (ngModelChange)="updateFilterValue($event)">
                <option *ngFor="let jobType of jobTypeObservable" [value]="jobType"> {{jobType.name}}</option>
              </select>
            </label>
        </div>
    
        <div *ngIf="jobsDataAvailable()" class="col-xs-6 col-sm-6 col-md-6 col-lg-6">
          <div class="has-text-centered">
            <pagination-controls (pageChange)="page = $event" class="my-pagination" directionLinks="true" maxSize="5"
                                 nextLabel="" previousLabel=""></pagination-controls>
          </div>
        </div>
      </div>
    
      <div *ngIf="jobsDataAvailable()">
        <div *ngFor="let job of (jobsObservable) | stringFilter: this.jobsForm.controls['jobTypeControl'].value  | paginate: { itemsPerPage: 10, currentPage: page }" class="row" style="margin-top: 10px">
          <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
            <div class="card">
              <div class="card-body">
                <h5 class="card-title">{{job.title}}</h5>
                <h6 class="card-subtitle mb-2 text-muted">{{job.city}}, {{job.state}}</h6>
                <p class="card-text">This text will be replaced by clearance value in future</p>
                <a class="btn btn-primary" href="https://bcmcllc.applytojob.com/apply/{{job.board_code}}">View and Apply</a>
              </div>
            </div>
          </div>
        </div>
      </div> <!-- End of ngIf-->
      </form>
    
    </div>

Custom Filter:

     import {Pipe, PipeTransform} from "@angular/core";
        @Pipe({
          name: 'stringFilter'
        })
        export class StringFilterPipe implements PipeTransform
        {
          transform(value: string[], filterValue: any)
          {
            if (!filterValue || filterValue === '')
            {
              return value;
            }
            return value.filter(item => -1 < item.toLowerCase().indexOf(filterValue.toLowerCase()));
          }
        }
**JobsListComponent**
    import {Component, OnChanges, OnInit, SimpleChanges} from '@angular/core';
    import {JobsService} from './services/jobs.service';
    import {SERVER_API_URL} from '../../app.constants';
    import {Observable} from 'rxjs';
    import {Job} from './model/job';
    import {FormControl, FormGroup} from '@angular/forms';
    import {JobType} from './model/job-type';
    
    @Component({
      selector: 'app-jobs-list',
      templateUrl: './jobs-list.component.html',
      styleUrls: ['./jobs-list.component.css']
    })
    
    export class JobsListComponent implements OnInit
    {
      jobsObservable: Observable<Job[]>;
      jobTypeObservable: Observable<JobType[]>;
      page: number = 1;
    
      jobsForm = new FormGroup({
        jobTypeControl: new FormControl({value: '', disabled: false})
      });
    
      //this.form.controls['jobTypeControl'].value
      //jobsForm.get('jobTypeControl').value
      constructor(private jobsService: JobsService) {
      }
    
      ngOnInit()
      {
        this.getAllJobTypes();
        this.getAllJobs();
      }
    
      getAllJobs() {
        let url = SERVER_API_URL + 'jobs/all';
    
        this.jobsService.getAllJobs(url).subscribe(
          data => {
            // @ts-ignore
            this.jobsObservable = data;
          },
          error => console.error('Failed to retrieve values from backend, error=> ' + error),
          () => console.log('Jobs retrieved from backend'));
        return this.jobsObservable;
      }
    
      getAllJobTypes() {
        let url = SERVER_API_URL + 'jobtypes/all';
    
        this.jobsService.getAllJobTypes(url).subscribe(
          data => {
            // @ts-ignore
            this.jobTypeObservable = data;
          },
          error => console.error('Failed to retrieve values from backend, error=> ' + error),
          () => console.log('Job Types retrieved from backend'));
        return this.jobTypeObservable;
      }
    
      jobsDataAvailable() {
        return this.jobsObservable !== undefined;
      }
    
    
      updateFilterValue(event)
      {
        console.log("Emitted Value "+event);
      }
    }

Solution

  • Two things.

    First: In your options you have

        <option *ngFor="let jobType of jobTypeObservable" [value]="jobType"> 
              {{jobType.name}}
        </option>
    

    So, the value is an object of type jobType. You can use, eg. if your jobType has a property called "id" [value]=jobType.id

        <option *ngFor="let jobType of jobTypeObservable" [value]="jobType.id"> 
              {{jobType.name}}
        </option>
    

    So, you received in your function the "id", not the whole object.

    Second: In reactive Form, usually you subscribe to values changes -it's not used (changed)- then, after create the form

        jobsForm.get('jobTypeControl').valueChanges.subscribe(value=>
           { //here you has the value of jobTypeControl
              console.log(value)
           }
        )