48

I have an Observable array and I want to filter/find the Project by name. When I try to use the filter option it is saying

enter image description here

ProjectService.ts

import { Injectable } from '@angular/core';
import { Project } from "../classes/project";
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';

import { Http } from '@angular/http';


@Injectable()
export class ProjectService {

  private projects: Observable<Project[]>;

  constructor(private http: Http) {
    this.loadFromServer();
  }

  getProjects(): Observable<Project[]> {
    return this.projects;
  }

  private loadFromServer() {
    this.projects = this.http.get('/api/projects').map(res => res.json());
  }

  getProjectByName(name: String) {
    return this.projects.filter(proj => proj.name === name);
  }


}

Project Class

export class Project {
    public name: String;
    public miniDesc: String;
    public description: String;
    public category: String[];
    public images: any[];
}
0

2 Answers 2

75

it should be:

getProjectByName(name: String) {
  return this.projects
    .map(projects => projects.filter(proj => proj.name === name));
}

you misunderstood about filter operator. The operator using to filter data return from stream. Your stream return array of object, so you need filter array to get you needed value.

The solution above will return an array after filtered, if you wanna get only one value, using following solution

getProjectByName(name: String) {
  return this.projects
    .map(projects => {
      let fl = projects.filter(proj => proj.name === name);
      return (fl.length > 0) ? fl[0] : null;
    });
}
Sign up to request clarification or add additional context in comments.

2 Comments

You can also just write a for-loop inside the map arrow function which returns the first value that satisfies the condition: .map(xs => { for (let x of xs) if (/*cond*/) return x; return null; }) etc.
Very nice solution provided by @Tiep Phan, only small note. Solution above work for array with primitive types, if you want to filter objects you can do something like: tasks.filter((item) => this.tasks.map((task) => task.id).indexOf(item.id) < 0
-1

In your Service you can define <any> type or Project[] type to return the response value and same could be continue with filter. e.g. <any>res.json() or <Project[]>res.json()

and also update your class as suggested by @Sajeetharan

ProjectService.ts

import { Injectable } from '@angular/core';
import { Project } from "../classes/project";
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';

import { Http } from '@angular/http';


@Injectable()
export class ProjectService {

  private projects: Observable<Project[]>;

  constructor(private http: Http) {
    this.loadFromServer();
  }

  getProjects(): Observable<Project[]> {
    return this.projects;
  }

  private  loadFromServer(): Observable<any> {
    this.projects = this.http.get('/api/projects').map((res: Response)=> <any>res.json());
  }

  getProjectByName(name: string) {
    return this.projects.filter(proj => proj.name === name);
  }   
}

*always write your filters, conditions or manipulation in component not in services.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.