1

I try to display an array of object, multiple function will have to alter it. So i try to make it an observable (maybe i'm wrong).

Typescript version : 2.7.2 rxjs : 6.2.1 angular cli : 6.0.8 Node : 8.11.3 Angular : 6.0.7

I have a variable in my service(IsolementService) declared as:

public listeIsolements$: Observable<isolementInterface>;

I have two main method in my service

getIsolements(mydate1:any, mydate2:any){
    let dateToSend = ""
    let headers =  {headers: new  HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded'})};
    this.http.post('foo/mywebservice.php', dateToSend, headers).subscribe((data:  Observable<isolementInterface>) => {
        this.listeIsolements$ = data;
    });
}

alteredList(mode:string){
    // Some alteration to listeIsolements$, without http call
}

Interface :

export interface RENOUVELLEMENT {
    _PERSON_ID?: any;
    _ACTIVITY_ID: string;
    _UF: string;
    _PRESCRIPTEUR_RENOUVELLEMENT: string;
    _ISOLEMENT_CH_STANDARD?: any;
    _ISOLEMENT_COMMENTAIRE?: any;
    _MODIF_MESURE_SOIN_DT_TM: string;
    _MOTIF_MAINTIEN?: any;
    _DATE_RENOUVELLEMENT: string;
}

export interface ISOLEMENT {
    _PERSON_ID: string;
    _ACTIVITY_ID: string;
    _ACTIVITY_ID_FIN: string;
    _NOM: string;
    _PRENOM: string;
    _IPP: string;
    _IEP: string;
    _DATE_NAISSANCE: string;
    _SEXE: string;
    _DEBUT_SEJ: string;
    _FIN_SEJ: string;
    _PRESCRIPTEUR: string;
    _DEBUT_ISOLEMENT: string;
    _FIN_ISOLEMENT: string;
    _UF: string;
    _CHAMBRE_STANDARD: string;
    _RAISON_CHAMBRE_STANDARD: string;
    _PATIENT_INFORME_MODALITE: string;
    _FAMILLE_PREVENU: string;
    _MODE_HOSPI: string;
    _INDICATIONS: string;
    _MESURES_PREVENTIVES: string;
    _CIRCONSTANCES?: any;
    _MED_PRESCRI_SORTIE: string;
    _OBSERVATIONS_SORTIE?: any;
    _RENOUVELLEMENTS: RENOUVELLEMENT[];
}

export interface isolementInterface {
    ISOLEMENTS: ISOLEMENT[];
}

My service is call in component :

constructor(public IsolementService : IsolementService, public myGestionUserService : GestionUserService) { }
ngOnInit() {
}


/*________________________________________________________________________________________________________*/
// Fonction call on submit
onSubmit(form: NgForm) {
    const send_date_deb = form.value['date_deb'];
    const send_date_fin = form.value['date_fin'];
    this.IsolementService.getIsolements(send_date_deb, send_date_fin);
}

But when i compile i have a an error TS2495 : type 'Observable'' is not an array or a string type. Who can i declare what i need ?

Thanks !

EDIT - code of view :

<tr *ngFor="let iso of IsolementService.listeIsolements$ | async">
                            <td class="filterable-cell">{{ iso._NOM }}</td>
                            <td class="filterable-cell">{{ iso._PRENOM }}</td>
                            <td class="filterable-cell">{{ iso._IPP }}</td>
                            <td class="filterable-cell">{{ iso._IEP }}</td>
                            <td class="filterable-cell">{{ iso._DATE_NAISSANCE }}</td>
                            <td class="filterable-cell">{{ iso._SEXE }}</td>
                            <td class="filterable-cell">{{ iso._DEBUT_SEJ }}</td>
                            <td class="filterable-cell">{{ iso._FIN_SEJ }}</td>
                            <td class="filterable-cell">{{ iso._DEBUT_ISOLEMENT }}</td>
                            <td class="filterable-cell">{{ iso._FIN_ISOLEMENT }}</td>
                            <td class="filterable-cell"></td>
                            <td class="filterable-cell">{{ iso._PRESCRIPTEUR }}</td>
                            <td class="filterable-cell">{{ iso._UF }}</td>
                            <td class="filterable-cell"></td>
                            <td class="filterable-cell">{{ iso._CHAMBRE_STANDARD }}</td>
                            <td class="filterable-cell">{{ iso._RAISON_CHAMBRE_STANDARD }}</td>
                            <td class="filterable-cell">{{ iso._PATIENT_INFORME_MODALITE }}</td>
                            <td class="filterable-cell">{{ iso._FAMILLE_PREVENU }}</td>
                            <td class="filterable-cell">{{ iso._MODE_HOSPI }}</td>
                            <td class="filterable-cell">{{ iso._INDICATIONS }}</td>
                            <td class="filterable-cell">{{ iso._MESURES_PREVENTIVES }}</td>
                            <td class="filterable-cell">{{ iso._CIRCONSTANCES }}</td>
                            <td class="filterable-cell">{{ iso._MED_PRESCRI_SORTIE }}</td>
                            <td class="filterable-cell">{{ iso._OBSERVATIONS_SORTIE }}</td>
                        </tr>
6
  • 1
    What is the error trace ? Which line is in error ? Commented Jul 12, 2018 at 7:46
  • I have a feeling that you try to bind the list in the view or use it somewhere as an array. The result of the array is the object itself and not the array within that object.So if you want to get the array from Observable<isolementInterface> you would want result.ISOLEMENTS as defined in your interface. Commented Jul 12, 2018 at 8:00
  • @trichetriche My error is in my declaration. Commented Jul 12, 2018 at 8:09
  • @Gijs Post, yes i would like to use it as array in my component view, i would like it to be observable so when i alter it in some function my view will update (but maybe i misunderstood a concept) Commented Jul 12, 2018 at 8:09
  • @Pylouface Can you provide the code of your view so we can see what happens there? Commented Jul 12, 2018 at 8:12

2 Answers 2

2

I see what goes wrong. You make a call, but then you subscribe to it. Subscribing to an observable always return the value of the observable after it emits it. If you want to declare the variable as the observable itself, you simply assign it as the call:

this.listeIsolements$ = this.http.post('foo/mywebservice.php', dateToSend, headers);

You don't need to subscribe to it if you only want the observable itself. If you want to use the value later on in the view, you can simply pipe it there (or subscribe to it in the component later on, if thats what you want).

(Edit): In your view, change it to:

<div *ngIf="IsolementService.listeIsolements$ | async as isolements">
<tr *ngFor="let iso of isolements.ISOLEMENTS">

Seperate the async pipe from the *ngFor otherwise it won't work.

Sign up to request clarification or add additional context in comments.

3 Comments

I understand why what i did couln't work. I don't have any error, but my data don't display. In order to trigger the request, i need to call subscribe, if i use your syntax listeIsolements is an Observable but don't contain my webservice response
Angular 'subscribes' to the observable if you pipe it in the view, you don't need to worry about that. If your call's response does not contain the proper model, you might have some syntaxes wrong (i.e. your call returns something else than an isolementInterface )
100% right :) I did small syntaxes error in my view. Everything works fine, thanks !
0
let localArray: Observable<MyObject>[] = [];

Context for my solution: I had an ng table that I wanted to load with data. Then the user could click a row and edit the details. I wanted the table to refresh when they added/updated a bicycle.

HTML:

<ng-template #bikesTable>
      <app-bike-table (editBike)="loadBikeFromTable($event)" (deleteBike)="removeBikeFromTable($event)" [bikeDetails]="bikes" [columnHeaders]="displayedColumns"></app-bike-table>
    </ng-template>

Observable component.ts

export class BikeTableComponent implements OnInit {
  @Input() bikeDetails: Bike[] | any = null;
  @Input() columnHeaders: string[] = [];
  @Output() editBike: EventEmitter<Bike> = new EventEmitter<Bike>();
  @Output() deleteBike: EventEmitter<Bike> = new EventEmitter<Bike>();

  selection = new SelectionModel<Bike>(true, []);

  constructor() { }

  ngOnInit(): void {
  }

  loadBikeForEdit(bike: Bike) {
    return this.editBike.emit(bike);
  }
  requestBikeDelete(bike: Bike) {
    return this.deleteBike.emit(bike);
  }
}

Wrapping object component.ts

  loadBikes() {
    //Load Bikes
    let that = this;
    this.getBikes().then(function (results) {
      that.bikes = results;
    });
  }

  async getBikes(): Promise<Bike[]> {
    let tkn: String | null = this.token.getToken();
    if (tkn) {
      return this._fetchBikesFromBackend(this.bikeService.getBikes(tkn));
    }
    return [] as Bike[];
  }

2 Comments

How do you add to it? Update it?
@ScipioAfricanus, apologies. I didn't see the comment till today. I added some more context to my answer, but basically you load it with a promise that returns an array.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.