0

There is a input text that for each change, he get from my service the search results. My serivce returns : Observable that contain all the results. It will return multiple persons.

tamplate.html:

<input type="text" id="inputSearch">
...
<tr *ngFor="let person of items$ | async" ...
...

Code:

import { Component ,OnInit} from '@angular/core';
import {Control} from '@angular/common';
import {PersonService} from "./person.service";
import {Person} from "./person.class";
import {Observable} from "rxjs/Rx"

@Component({
  selector: 'contact-table',
  moduleId: module.id,
  templateUrl: 'contact-table.component.html',
  styleUrls: ['contact-table.component.css']
})
export class ContactTable implements OnInit {
  private items$: Observable<Person[]>;
  private inputChanged$:Observable<{}>;

  constructor(private _PersonService:PersonService) {}

  public ngOnInit() {
    this.inputChanged$=Observable.fromEvent(document.getElementById("inputSearch"), 'input');
    this.items$= this.inputChanged$
      .map((event:any)=>event.target.value)
      .switchMap((value:string) =>{
        return this._PersonService.getPersons(); <<-- it gets here!****
      })
      .toArray();
    this.items$.subscribe((persons:Person[])=>{
      console.log(persons); <<-- it doesn't gets here!****
    });
  }
}

Update1:

By Günter Zöchbauer tip, I added menual subscription in the last line of the method but that code is never excuted and nothing gets logged. Any idea why?

Update2: I added the full ts file of my code.

Updated3:

Solved - But don't know why: ( I moved toArray() )

  public ngOnInit() {
    this.inputChanged$=Observable.fromEvent(document.getElementById("inputSearch"), 'input');
    this.items$= this.inputChanged$
      .map((event:any)=>event.target.value)
      .switchMap((value:string) =>{
        return this._PersonService.getPersons().toArray(); <<-- moved here
      }); <<-insead of here.

    this.items$.subscribe((persons:Person[])=>{
      console.log(persons); <<-- it doesn't gets here!****
    });

Any idea why it made any diffrence?

Stav Alfi
  • 13,139
  • 23
  • 99
  • 171
  • Have you tried to output what you actually get when you subscribe to `items$`. According to the error message it is an object but `*ngFor` requries an array. – Günter Zöchbauer Jul 19 '16 at 10:56
  • Thanks for the tip, I updated the post and said that nothing gets logged in items$.subsribe(personsArray=> console.log(personsArray)) – Stav Alfi Jul 19 '16 at 11:07
  • Weird, why would `*ngFor` complain about an object if there is nothing emitted. – Günter Zöchbauer Jul 19 '16 at 11:08
  • As you said in your comment, async accepets only arrays so I removed the sencond version of the code that gived me error. Now there is no error but nothing gets excuted. – Stav Alfi Jul 19 '16 at 11:10
  • I'd try to move the code to `ngAfterViewInit()`. The input referenced in `this.inputChanged$=Observable.fromEvent(document.getElementById("inputSearch"), 'input');` might not yet exist. I also would use `@ViewChild('myInput') input:ElementRef;` and ` this.inputChanged$=Observable.fromEvent(this.input.nativeElement, 'input');` – Günter Zöchbauer Jul 19 '16 at 11:22
  • the code gets to .switchMap with the current letter I pressed so there is not problem with that. But I changed anyway as you said for future errors. – Stav Alfi Jul 19 '16 at 11:43
  • I don't know rxjs well enough to help here. I'm using Dart and there are streams instead of observables. – Günter Zöchbauer Jul 19 '16 at 11:45
  • Okay I solved it: I moved returned in the swichMap this._PersonService.getPersons().toArray() insead of puting toArray() in the end of the chain. I got no idea why it fixed the problem but it did :) Thanks anyway for all the help and the tips Günter Zöchbauer. – Stav Alfi Jul 19 '16 at 11:48
  • Do you need `toArray` at all? Doesn't `getPersons()` return an `Observable` already? – Günter Zöchbauer Jul 19 '16 at 11:50
  • My service.getPersons() returns Observable. – Stav Alfi Jul 19 '16 at 11:51
  • Why not `Observable`? – Günter Zöchbauer Jul 19 '16 at 11:54
  • Currently now, I don't talk to a real server and I understood that Observable will return from the real server (when i will have one) person after person instead all the persons togheter so its seems like I won't use Observable as I should have if I wait to the real server to get all the data and only then send a promise with all the persons. By that reason I send from y service person after person. Am I currect by the way Observable behives? – Stav Alfi Jul 19 '16 at 11:59
  • I see. It makes sense to move the `toArray()` inside otherwise `toArray()` would wait until the `inputChanged$` observable completes (which is not supposed to happen) to return the array (when all events are collected). Inside `toArray()` waits for `getPersons()` to complete and then emits the collected array (once fore every `getPersons()` request) – Günter Zöchbauer Jul 19 '16 at 12:15
  • If we remove toArray() then any other method that will come afterm swichMap(..) will use the same object getPersons() returning. So it don't matter after which one we put toArray(); All in all, my solution should not work. – Stav Alfi Jul 19 '16 at 12:24
  • With my limited rxjs knowledge I think without `toArray()` `inputChanged$` will output a series of single `Person` items (the results of several `getPerson()` calls will also be emitted like from one request that returns single `Person` events just multiple times) which `ngFor` can't work with. – Günter Zöchbauer Jul 19 '16 at 12:28
  • Okay, Thank you for all the help! – Stav Alfi Jul 19 '16 at 12:34

0 Answers0