8

I'm using angular 4 and I try to get data from 2 endpoints but I have a problem understanding rxjs.

with this code I can only get list of students and users only.

 getStudent() {
    return this.http.get(this.url + this.student_url, this.getHeaders()).map(res => res.json());
  }

getUsers() {
    return this.http.get(this.url + this.users_url, this.getHeaders()).map(res => res.json());
  }

Let's say this is data : Student

[{"ID" : 1 , "SchoolCode": "A150", "UserID": 1 }, 
{"ID" : 5 , "SchoolCode": "A140" , "UserID": 3}, 
{"ID" : 9 , "SchoolCode": "C140" , "UserID": 4}]

User

[{"ID" : 1  ,"Name": "Rick" , "FamilyName" , "Grimes" },
{"ID" : 4 ,"Name": "Carle" , "FamilyName" , "Grimes" }]

I want to get first all students then compare UserID if it's the same as user then I combine both objects into one until I get an array like this :

{"ID" : 1 , "SchoolCode": "A150","Name": "Rick" , "FamilyName" , "Grimes" }

I think I should use flatmap but I did try write code but it dosen't work for me and I didn't find an example with such logic.

Could you please help me.

1
  • flatmap allows you to change streams, for example, you could ask for the students and then get the list of courses for a particular student that would be a good option; in this case you always need both lists and then you can do some logic, so you might need forkjoin, merge or combine to do so Commented Sep 1, 2017 at 6:04

2 Answers 2

7

You can use the switchMap operator (alias of flatMap) in the following code :

// Observables mocking the data returned by http.get()
const studentObs = Rx.Observable.from([
  {"ID" : 1 , "SchoolCode": "A150", "UserID": 1 }, 
  {"ID" : 5 , "SchoolCode": "A140" , "UserID": 4}, 
  {"ID" : 9 , "SchoolCode": "C140" , "UserID": 3}
]);
const userObs = Rx.Observable.from([
  {"ID" : 1, "Name": "Rick" , "FamilyName": "Grimes" },
  {"ID" : 3, "Name": "Tom" , "FamilyName": "Cruise" },
  {"ID" : 4, "Name": "Amy" , "FamilyName": "Poehler" }
]);
// Return an observable emitting only the given user.
function getUser(userID) {
  return userObs.filter(user => user.ID === userID);
}

studentObs
  .switchMap(student => {
     return getUser(student.UserID).map(user => {
       // Merge the student and the user.
       return Object.assign(student, {user: user});
     })
  })
  .subscribe(val => console.log(val));

Check out this JSBin: http://jsbin.com/batuzaq/edit?js,console

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

Comments

0

You could try the following:

import { forkJoin } from 'rxjs/observable/forkJoin';

interface Student {
  id: number;
  schoolCode: string;
  userId: number;
}

interface User {
  id: number;
  name: string;
  familyName: string;
}

interface Merged {
  id: number;
  schoolCode: string;
  name: string;
  familyName: string;
}

getStudents(): Observable<Student[]> {
    // Implementation
  }

  getUsers(): Observable<User[]> {
    // Implementation
  }

  getMerged(): Observable<Merged[]> {
    const student$ = this.getStudents();
    const users$ = this.getUsers();
    const merged$ = forkJoin(student$, users$)
      .map(src => src[0].reduce((acc, current) => {
        // acc is the accumulated result (list with mapped objects)
        // current is an element of the students list
        const user = src[1].find(u => u.id === current.userId);
        // check if there is a user associated to the current student element
        if (user) { // if there is a matching user, push new element to result list
          acc.push({
            id: user.id,
            name: user.name,
            familyName: user.familyName,
            schoolCode: current.schoolCode
          });
        }
        return acc;
        // this could be changed to use a more immutable based approach
      }, new Array<Merged>()));
      // the seed value to start accumulating results is an empty list
    return merged$;
  }

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.