Reputation: 1699
I have an observable
public get users(): Observable<User[]> {
return this.userData.asObservable();
}
I want to create another observable from this
public get usedRoles(): Observable<Roles[]> {
// create the observable to get all the roles from all users
}
Where each User
has an attribute roles: Array<Role>
I tried flatMap
however getting stuck with the getting the right structure.
public get usedRoles(): Observable<Role[]> {
return this.users.flatMap(users => users.map(u => u.roles));
}
But this is just giving me arrays of roles separately for each user as shown by this this.usedRoles.subscribe(roles => console.log(roles));
I want a single array with the distinct list of roles used by all users.
Thanks so much for help!
Upvotes: 1
Views: 162
Reputation: 21387
try this
public get usedRoles(): Observable<Role[]> {
return this.users.flatMap((users) => {
const roles = [];
users.forEach((user) => {
// roles = roles.concat(user.roles);
user.roles.forEach(r => {
if (!roles.some(role => role.id === r.id)) {
roles.push(r);
}
});
});
return Observable.of(roles);
});
}
Upvotes: 1
Reputation: 16847
If you are mapping a value into another value you can use the regular map
operator.
flatMap
should be when the result returned by your projection function is another observable.
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs/Observable';
getUserRoles(): Observable<Role[]> {
return this.users.pipe(
map(users => users.reduce((roles, user) => [...roles, ...user.roles], [])),
map(arr => [...new Set(arr)])
)
}
Upvotes: 0