0
votes

First of all, I’m new at Angular. I’m developing an application that integrates AngularJS as frontend and Yii2 as backend. So far everything was doing fine but in the last few weeks I was dealing with an Angular Material headache. I’ve been searching a lot but I couldn’t find the solution.

I’m trying to code a Form with around 10 autocomplete material elements. My data is being fetched by API REST in an Angular Service as an observable. In each autocomplete element I can easily display the options but the problem comes when I try to bind/get the id of the object. DisplayWith just gives me the value of id while I was expecting at least the full object so I can return the name and others properties of the object. I the expect [displayWith] to give me back the whole object so I can treat what property I can return to display.

I’ve seen how to do this with an array of objects or a simple array, but I don’t know how to do it using observables from my Rest Api. Also, I don’t know if is really efficient, for example, to manage so many observables in a form.

I’ve read this feature but unlikely didn’t help me. Even I found some solutions, I havent found any for Observables. Maybe I'm facing wrong the whole thing. Thanks in advance and i will really aprecciate i someone could help me.

So far this is my code for only one autocomplete element.

Angular component

import { Component, OnInit } from '@angular/core';
import { FormBuilder,FormGroup, Validators, FormControl } from '@angular/forms';
import { Observable } from 'rxjs';
import { startWith, debounceTime, switchMap, map, distinctUntilChanged } from 'rxjs/operators';

import { DedicacionI } from '../../../models/dedicacion.interface'
import { DedicacionesService } from 'src/app/services/dedicaciones.service';

export class DocenteAltaComponent implements OnInit {
 
  myForm = new FormGroup()

  myControlDedicaciones = new FormControl();
  dedicacionesList: Observable<DedicacionI[]>;
  filteredOptionsDedicaciones: Observable<DedicacionI[]>;

  constructor (
    public fb:FormBuilder,

    private dedicaciones:DedicacionesService,
    ) 
    
    { 

      this._getDedicacionesData();

      this.filteredOptionsDedicaciones = this.myControlDedicaciones.valueChanges.pipe(
        startWith(null),
        debounceTime(200),
        distinctUntilChanged(),
        switchMap(val => {
          return this._filterDedicaciones(val || '')
        })
      )
    }
    
  private _getDedicacionesData():void {
    this.dedicacionesList = this.dedicaciones.getDedicaciones();
  }

  private _filterDedicaciones(val: string) {
    return this.dedicacionesList.pipe(
      map(response => response.filter(option => {
        let aux = option.denominacion.toString();
        return aux.toLowerCase().indexOf(val.toString().toLowerCase()) === 0
      }))
    )
  }

  public displayDedicacion (dedicacionSel): string {
    if (dedicacionSel != null){
      return dedicacionSel.denominacion + " (" + dedicacionSel.codigo + ")";
    }else{
      return "";
    }
  }
}  

Angular html

<form [formGroup]="myForm" (ngSubmit)="save(myForm.value)">

    <!-- Dedicaciones -->
    <p>
        <mat-form-field class="example-full-width">
        <input type="text"
            placeholder="Dedicación"
            aria-label="Number"
            matInput
            [formControl]="myControlDedicaciones"
            [matAutocomplete]="autoDededicacion">
            <mat-autocomplete autoActiveFirstOption #autoDededicacion="matAutocomplete" [displayWith]="displayDedicacion">
            <mat-option *ngFor="let option of filteredOptionsDedicaciones | async" [value]="option">
                <p>{{option.denominacion}} ({{option.codigo}}) </p>
                                
            </mat-option>
            </mat-autocomplete>
        </mat-form-field>
    </p>
    <!-- /.Dedicaciones -->

</form>

Angular service

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { DedicacionI } from '../models/dedicacion.interface';

@Injectable()

export class DedicacionesService {

  constructor(private http:HttpClient) { }

  getDedicaciones() {

    return this.http.get<DedicacionI[]>("http://localhost/yii2-tests/rest/web/index.php/v1/dedicaciones")
          
  }

}
1

1 Answers

1
votes

It doesn't look like you are subscribing to the service call so you need to do that or you will never get any data. Something like this:

    private _getDedicacionesData():void {
        this.dedicaciones.getDedicaciones().subscribe(
        
        returnValueFromService =>{        
            this.dedicacionesList = returnValueFromService.data
}
        );          
}

You probably want to "prove" you can get data before you start implementing the material controls. It is good practice to build bit by bit

You should also do your service calls in ngoninit as its bad practice to do it in your constructor