What is the best way to implement asynchronous guarding for users?

Seeking assistance with implementing async route guard.

I have a service that handles user authentication:

@Injectable()
export class GlobalVarsService {

    private isAgreeOk = new BehaviorSubject(false);

  constructor() { };

  getAgreeState(): Observable<boolean> {
    return this.isAgreeOk;
  };  

  setAgreeState(state): void {
    this.isAgreeOk.next(state);    
  };   
}

If the method getAgreeState() returns true, then the user is authenticated.

Here is my guard service:

import { GlobalVarsService } from '../services/global-vars.service';


@Injectable()
export class AgreeGuardService implements CanActivate {

  constructor(private router: Router,
                        private globalVarsService: GlobalVarsService) { };

  canActivate() {
    this.globalVarsService.getAgreeState().subscribe(
    state => {
      if(!state) {
            this.router.navigate(['/agree']);
            return false;
      } else {
        return true;
      }      

    }); 
  }  

}

These are my routes:

const routes: Routes = [
  {
    path: 'agree',
    children: [],
    component: AgreeComponent
  },    
  {
    path: 'question',
    children: [],
    canActivate: [AgreeGuardService],
    component: QuestionComponent
  }, 

However, I encountered the following error message in the console:

ERROR in /home/kalinin/angular2/PRACTICE/feedback/src/app/services/agree-guard.service.ts (8,14): Class 'AgreeGuardService' incorrectly implements interface 'CanActivate'. Types of property 'canActivate' are incompatible. Type '() => void' is not assignable to type '(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => boolean | Observable | Pr...'. Type 'void' is not assignable to type 'boolean | Observable | Promise'.

Since GlobalVarsService and its methods are also used in other components, modifying them is not an option for me.

Answer №1

In order to properly handle the subscription and return a value, it's recommended to use map instead of subscribe. Additionally, don't forget to include a return statement within your code.

canActivate() {
  // Include the 'return' statement
  return this.globalVarsService.getAgreeState()
   // Use 'map' instead of 'subscribe'
   // .subscribe(state => {
   .map(state => {
     if(!state) {
        this.router.navigate(['/agree']);
        return false;
     }
     return true;
   }); 
 }  

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for accessing the previous route - the route that led me to the current page

Is there a way to retrieve the previous route in Angular while knowing the current route? For example, moving from tab http://localhost:4200/test/testNav/ABC to http://localhost:4200/test/SampleNav/XYZ. I need to access the previous URL (/ABC) in the ngOn ...

Angular Dynamic Alert Service

Is it possible to customize the text in an Angular Alert service dynamically? I'm looking to make certain words bold, add new lines, and center specific parts of the text. Specifically, I want the word "success" to be bold and centered, while the rest ...

What could be causing my select tags to appear incorrectly in Firefox and IE?

With the help of Jquery, my goal is to dynamically populate a select field when it is in focus, even if it already has a value. Once populated, I want to retain the previous value if it exists as an option in the newly populated field. Although this works ...

Unable to replicate the function

When attempting to replicate a function, I encountered a RootNavigator error Error in duplicate function implementation.ts(2393) I tried adding an export at the top but it didn't resolve the issue export {} Link to React Navigation options documen ...

Tips on how to modify a select option in vue based on the value selected in another select

My Web Api has methods that load the first select and then dynamically load the options for the second select, with a parameter passed from the first selection. The URL structure for the second select is as follows: http://localhost:58209/api/Tecnico/Tanq ...

Hosted-Git-Info Regular Expression Denial of Service attack

I am facing a vulnerability in my Ionic/Angular app. The issue suggests updating the version of hosted-git-info. However, I cannot find this package in my package.json file. Can you provide guidance on how to resolve this? https://www.npmjs.com/advisorie ...

How to display an [object HTMLElement] using Angular

Imagine you have a dynamically created variable in HTML and you want to print it out with the new HTML syntax. However, you are unsure of how to do so. If you tried printing the variable directly in the HTML, it would simply display as text. This is the ...

Tips for managing Angular modules post-splitting and publishing on npm

Currently, I am in the process of developing an Angular application. To ensure reusability and prevent duplication of components and services in another application, I have divided the app into modules and deployed them on a private npm and git server. No ...

problems with using array.concat()

I am attempting to reverse a stream of data using a recursive call to concatenate a return array. The instructions for this problem are as follows: The incoming data needs to be reversed in segments that are 8 bits long. This means that the order of thes ...

AmCharts Axis renderer mistakenly renders an additional grid line

I have successfully created a basic XYChart using amcharts4. To get rid of the grid lines on the x-axis, I changed the stroke opacity for the x-axis grid to 0 using the following code: xAxis.renderer.grid.template.strokeOpacity = 0; Everything was workin ...

Issues with applying different styles in a React Component based on prop values are hindering the desired outcome

I am currently working on a Display component that is supposed to show an item. The item should be styled with the css property text-decoration-line, applying line-through when the Available prop is set to false, and no decoration when set to true. Howev ...

Obtain the value stored in the variable named "data"

I'm trying to calculate the sum of data values using jQuery, similar to this example: { label: "Beginner", data: 2}, { label: "Advanced", data: 12}, { label: "Expert", data: 22}, and then add them together. Like so: var sum = data1+data2+dat ...

How can I apply styling to Angular 2 component selector tags?

As I explore various Angular 2 frameworks, particularly Angular Material 2 and Ionic 2, I've noticed a difference in their component stylings. Some components have CSS directly applied to the tags, while others use classes for styling. For instance, w ...

Issue with ngfactory.js warning in Angular 6+ when building in production mode, but the development build is running without any

I am encountering an error while trying to build Angular for production. Can someone please provide a solution to this issue? WARNING in ./src/app/userforms/login/login.component.ngfactory.js 149:679-708 "export 'MAT_PROGRESS_BAR_LOCATION' (impo ...

Selenium on Sauce Labs does not successfully load the page in Firefox after clicking

An issue has arisen where a test that functions properly with selenium webdriver locally is timing out when executed remotely on saucelabs.com. Notably, the test runs smoothly for Chrome in both local and remote scenarios. The problem seems to lie in the ...

Ways to set a background image for two separate components in Angular

Trying to figure out how to integrate this design: https://i.sstatic.net/r70a4.png The challenge lies in having a background image that spans across the navbar and the content below it. Currently, the code separates the navbar component from the content ...

What is the best way to incorporate the .top offset into a div's height calculation?

Looking to enhance the aesthetic of this blog by adjusting the height of the #content div to match that of the last article. This will allow the background image to repeat seamlessly along the vertical axis. I attempted the following code: $(document).re ...

Is there a way to display a message in a div container instead of using the alert box when there is a successful ajax response?

Hey there, I'm currently working on implementing error validation handling for a custom form that I've created. I'm looking to display the error messages in a designated div rather than using the standard browser alert box. Since I'm fa ...

How can I ensure that Mongoose is case sensitive?

Currently, our authentication system is case sensitive for the email input. However, I would like to make it case insensitive. Here is the function in question: Auth.authenticate({ email, password }) Auth represents a mongoose Model that stores users in ...

Error encountered during conversion from JavaScript to TypeScript

I am currently in the process of converting JavaScript to TypeScript and I've encountered the following error: Type '(props: PropsWithChildren) => (any[] | ((e: any) => void))[]' is not assignable to type 'FC'. Type '(a ...