Igor Simic
4 years ago

How to return boolean from Angular observable


How to return true or false, or any value from Observable? If you have tried to return complete subscribe method you will get the observer object and not the value. So, if for example, we have to hide or show some content based on observable data we need how we are going to do that?

In our example, we will check does user contain role-admin and based on the show - hide some content.

First, lets create Observable and let's create list of "random roles" which we will assign to current role, and array of master roles where we will check does master role array contains current role:
import { Observable } from 'rxjs/Observable';

// ....
export class AppComponent  {
  // create a list of random roles
  private roles = [
    {name:"Role Admin", slug:"role-admin"},
    {name:"Role User", slug:"role-user"},
    {name:"Role Manager", slug:"role-manager"},
    
  ];

  // put our master/admin roles in object so we can check it against current role
  private rolesAdmin = [

    {name:"Role Admin", slug:"role-admin"},
    {name:"Role Master", slug:"role-master"}
    
  ];
}



Next let's add variables roleList$ (observable) and currentRole which we will set to empty
public roleList$;
public currentRole = '';

Now let's create our Observable and assign rolesAdmin to it, we will do it by using onInit angular method and create a method for assigning random role:
ngOnInit(){
    
    // let's create observable and put the roles as a value 
    this.roleList$ = Observable.create(observer => {
        observer.next(this.rolesAdmin);
        observer.complete();
    });

    //this.currentRole = this.randomRole();

    this.randomRole();

  }
randomRole(){

    let getRole= this.roles[Math.floor(Math.random() * 3) + 0];
    console.log("random role id");
    console.log(Math.floor(Math.random() * 2) + 0);
    console.log(getRole.slug)
    this.currentRole = getRole.slug;

  }

OK, so now let's create our HTML, where we will have content which should be visible only on if user have role-admin:
<p>show content bellow only if user has role admin!</p>
<div style="width:50%;height:100px; border:1px solid black; border-style:dotted; padding:5px">
  <p *ngIf="(ifUserContaisRole(currentRole) | async)">
  Hello, i am visible only for role-admin!
</p>

</div>
<br>
<button (click)="randomRole()" >Change role</button>
<p>current role: <strong>{{currentRole}}</strong></p>
You may have noticed that we have method ifUserContaisRole(currentRole) which we did not yet created. This method will return true or false based on observable data. We will loop against the master roles and check do we have current role there and return boolean from observable bynot using subscribe method but pipe and map:
ifUserContaisRole(checkRole){ //return true or false

      console.log(checkRole);

      // let's assume we are getting list of roles from http request. So usually we will access the data like this
      this.roleList$.subscribe((data)=>{
        console.log(data);
      });

      // let's check do we have a role 'role-admin' in  our observable list of roles and return true or false

      // to achieve this we will use pipe and map methods and return the content of it which will be true or false
            return this.roleList$.pipe(map((roles)=>{
              
              // first check do we have any roles if not return false
              if (roles.length > 0 ){

                  for (let rolesKey in roles) {

                    if( roles[rolesKey].slug === checkRole ){
                        console.log("user does have role: "+checkRole);
                      
                        return true;
                    }

                  }


              } else{
                  console.log("no roles available");
                  return false;

              }

              return false;

            }));

  }

But be careful, do not use forEach method to loop, because you will not be able to return from it, it can not be broken (at least not easily) and it will not return but it will continue looping if we found our role.

Anyway, here is working example, just for you - you lazy mofo:

https://stackblitz.com/edit/angular-n7nn3d

UPDATE:
another more simple way is by using BehaviorSubject, please read here how to use it:
https://www.coditty.com/code/how-to-return-boolean-from-observable-using-behaviorsubject