0

I have an array of routes, which I'm trying to filter on depending if the service says the user has permission. I've tried various combination & transformative operators with no success mergeMap, concatMap, concatAll, mergeAll. The problem is that hasRoutePermission returns an observable that returns a boolean from the endpoint. Thanks in advance.

stackblitz

const exampleRoutes = [{
  model: 'ExampleModel'
}, {
  model: 'ExampleModel'
}, {
  model: 'ExampleModel'
}, {
  model: 'ExampleModel'
}];

filterRoutes(routes): Observable <[]> {
  const hasRoutePermission = (route: IRouteData): Observable <boolean> =>
    this.examplePermissionService.hasRoutePermission(route);

  return of(items)
  .pipe(
    filter(item => hasRoutePermission(item))// Problem is here
  )
}

I'm using an async pipe to subscribe to the filtered list in the template.

6
  • Hard to follow here, exampleRoutes isn't used. Can you make a stackblitz? Commented Sep 1, 2020 at 19:25
  • Your usage of items and item make me think that you haven't yet understood how filter works and that you're confusing the rxjs operator filter with the Array filter method. If the observable emits arrays, then filter operates on the entire array, not individual items of the array. Commented Sep 1, 2020 at 19:30
  • @Phix updated with stackblitz as close as possible to replicate. Commented Sep 1, 2020 at 19:40
  • @IngoBürk please help me understand :) Commented Sep 1, 2020 at 19:44
  • @alphapilgrim I suggest you read up on observables a bit. Two immediate issues come to mind with your example. 1) You're assigning the result of this.filterRoutes to this.routeItems - the returned type of this method is an Observable<[]>, and notably not an array. 2) You seem to be trying to handle this purely synchronously and that's not what Observables do - rather, they execute lazily and only when subscribed to (as in the answer below). In the subscribe method, you'll set routeItems to the result, not as an assignment from the function as you've got now. Commented Sep 1, 2020 at 19:55

1 Answer 1

2

So you receive boolean value inside Observable and now need to use one of "flattening" operators (like mergeMap, concatMap, etc) to get back primitive value:

const { of, from } = rxjs; // = require("rxjs")
const { mergeMap, filter, map, toArray } = rxjs.operators; // = require("rxjs/operators")

function hasRoutePermission(id) {
  return of(id % 2 === 0); // mock api logic
}

function filterRoutes(items) {
  return from(items).pipe(
    mergeMap(item =>
      hasRoutePermission(item).pipe(
        filter(permission => permission),
        map(() => item)
      )
    ),
    toArray()
  );
}

const filtered$ = filterRoutes([0,1,2,3,4,5]);
filtered$.subscribe(v => console.log(v));
<script src="https://unpkg.com/[email protected]/bundles/rxjs.umd.min.js"></script>

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

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.