"Angular TypeScript throws an error when a variable is assigned but remains undefined

I am currently facing an issue with the code snippet provided below. The constructor is utilizing router methods to retrieve the previous route and store a variable in it. However, when I call `ngOnInit()`, which then triggers another method that compares the saved variable from the constructor with values from a service, the stored variable always seems to be undefined at this point.

Interestingly, within the constructor, the value of `this.selBoard` is set to 40. Yet, whenever I print out the value using `console.log(this.selBoard);`, it constantly shows up as undefined.

I have confirmed that there are no syntax errors present in the async function calls. The fact that the correct value (40) is logged within the constructor indicates that the variable should not be undefined inside `getRouterDetails()`.

//...
selBoard : number;
selectedBoard : Board= new Board();

constructor(private router: Router) {
    this.router.events.pipe(filter((evt: any) => evt instanceof RoutesRecognized), pairwise())
        .subscribe((events: RoutesRecognized[]) => {
            var url = events[0].urlAfterRedirects;
            var urlIndex = url.indexOf('boardId=');
            var boardId = url.substring(urlIndex+8, urlIndex+10);
            this.selBoard = Number(boardId);
            console.log('selBoard --- '+this.selBoard);
        });
            
    ngOnInit(): void {
    //..
    if (this.loggedInUser.isAdmin)  {
        this.loadBoardsList();}
    ..//
    }
    
    
    loadBoardsList() { 
            this._boardService.loadBoards().subscribe( posts => {
                this.data = posts; 
                console.log('loadBoardsList', this.data);
            },
            error => { 
                console.log('loadBoardsList - error',error);
               // this._errorService.handleError(error); 
                this._messageService.add({severity:'error', summary:'Error Message', detail:error.error+' - '+error.message, sticky: true}); 
            }, 
            () => {  
                this.boardsList = this.data.boardLi; 
                this.getRouterDetails();
                console.log(this.selectedBoard);
            });  
    }
    
    getRouterDetails() {
       for (let i = 0; i < this.boardsList.length; i++) {
            console.log(this.boardsList[i].id);
            console.log(this.selBoard);
            if (this.boardsList[i].id == this.selBoard) {
                console.log('Which one selected ---'+this.selBoard);
                this.selectedBoard = this.boardsList[i];
            }
        }
     }

If anyone has any suggestions or insights on how to approach this issue, please feel free to share. Thank you!

Answer №1

It looks like you're taking a very convoluted approach to retrieving parameter values. Have you considered using this.route.queryParams instead?

constructor(private route: ActivatedRoute) { 
  this.route.queryParams.subscribe(params => {
    this.boardId = params.boardId;
  });
}

Answer №2

It is important to keep in mind that the .subscribe method operates asynchronously. If the .subscribe within the ngOnInit (loadBoardList()) function occurs before the .subscribe in the constructor, a race condition may arise where a property is undefined in one place and populated in another. It appears that these subscriptions are interdependent, suggesting the use of switchMap to manage them effectively.

import { switchMap } from 'rxjs/operators';
...
selBoard : number;
selectedBoard : Board= new Board();

    constructor(private router: Router){
      // remove code inside constructor
    }
            
    ngOnInit(): void {
    // ..
    if(this.loggedInUser.isAdmin)  {
        this.loadBoardsList();}
    // ..
    }
    
    
    loadBoardsList(){
        this.router.events.pipe(
            filter((evt: any) => evt instanceof RoutesRecognized), 
            pairwise(),
            switchMap((events: RoutesRecognized[]) => {
               var url = events[0].urlAfterRedirects;
               var urlIndex = url.indexOf('boardId=');
               var boardId = url.substring(urlIndex+8, urlIndex+10);
               this.selBoard = Number(boardId);
               console.log('selBoard --- '+this.selBoard);
               return this._boardService.loadBoards(); // switch to this observable now, once the previous is done
            }),    
        ).subscribe( posts =>{
                this.data = posts; 
                console.log('loadBoardsList',this.data);
                },
                error => { 
                console.log('loadBoardsList - error',error);
               // this._errorService.handleError(error); 
                this._messageService.add({severity:'error', summary:'Error Message', detail:error.error+' - '+error.message, sticky: true}); 
                }, 
                () => {  
                this.boardsList = this.data.boardLi; 
                this.getRouterDetails();
                console.log(this.selectedBoard);
            });  
    }
    
    getRouterDetails(){
       for (let i = 0; i < this.boardsList.length; i++) {
            console.log(this.boardsList[i].id);
            console.log(this.selBoard);
            if(this.boardsList[i].id == this.selBoard){
                console.log('Which one selected ---'+this.selBoard);
                this.selectedBoard = this.boardsList[i];
            }
        }
     }

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

Preventing the angular material mat-select from extending beyond the screen boundaries

Recently, I incorporated a mat-select into my Angular application following the guidance provided in this example: here However, one issue that has been bothering me is that when I select an option and reopen the list to choose another option, the list po ...

Utilizing Angular 8 (TypeScript) and .NET Core to send a GET request with dates as a parameter

I attempted to send 2 dates as parameters in the GET request, but I am only receiving this: Model public class Dates { public DateTime from { get; set; } public DateTime to { get; set; } } .net core [HttpGet] [Route("main/exportToEx ...

Clicking a button in React requires two clicks to update a boolean state by triggering the onClick event

I have a React functional component with input fields, a button, and a tooltip. The tooltip is initially disabled and should only be enabled and visible when the button is clicked and the input fields contain invalid values. The issue I'm facing is t ...

ServiceAccountKey cannot be located by Firebase deploy

I am in the process of integrating a serviceAccountKey into my Typescript cloud functions project. var serviceAccount = require("/Users/kareldebedts/myAppName/functions/serviceAccountKeyName.json"); admin.initializeApp({ storageBucket: "appName.appspot ...

The polyfills.js script encountered an error due to an undefined reference to exports at line 17

I recently started learning Angular JS and I'm following a tutorial on how to set up an Angular JS project using Visual Studio. However, I encountered an issue with an undefined "exports" variable in one of the JavaScript files (polyfill.js) included ...

Give a style attribute to every other child element within a class. Each class should function independently, including their final child which contains an if statement

UPDATE: I kindly request a review of the answers provided. Utilizing JavaScript for this task may not be the most efficient method. I will keep this question as it is, as it could potentially benefit someone else. The aim is for every ".ulInCollapse li" t ...

Change the name of an angular2 component to a string representation of "this"

When using an Angular2 Component, if you execute the following code: console.log (this); You will see the entire object with all its members, for example: "ComponentName {member1, member2, member_n}" Now, I am interested in only logging the ComponentNa ...

When I refresh the page in Angular2, the router parameters do not get loaded again

When loading my application on routers without parameters, everything is normal. However, when trying to use a router with params, the application fails to load. For example: localhost:3000/usersid/:id The code for the router is as follows: const appRou ...

Exploring support classes in an Angular application

Within my Angular project, I have not only component classes but also auxiliary classes for data model representation and data iterators. When Angular generates test classes for components, they are named in the format component-name.component.spec.ts I ...

What methods can I use to access the animalType in a generic type?

Can you guide me on how to access the value of the generic, static variable animalType in T.animalType from the given example code below? export class main { constructor() { var myWorker: worker = new worker(); myWorker.whatAmI(); ...

The error message "Element is not defined (Object.<anonymous>)" is occurring in the context of Intro.js-react, React, Next.js, and Tailwind

Here is a code snippet: import { useState } from 'react'; import { Steps } from 'intro.js-react'; export default function Dashboard() { const [stepEnabled, setStepEnabled] = useState(true); const steps = [ { intro: &apos ...

Incorporate the leaflet Draw feature into your Angular 2 application

I am a newcomer to Angular2, created using Cli. While I successfully imported Leaflet into my Angular2 project without any Angular2 directives, I am struggling to do the same with the Leaflet Draw extension. I haven't been able to make Draw work. In e ...

correctly inputting properties on a Next.js page

I am encountering an issue with my straightforward SSR-generated Next.js page. It seems that I have made a typing error along the way, causing the linter to flag it. export interface ProposalTag { id: number; name: string; hex: string; color: strin ...

Limit the range of potential inputs for the function parameter

class Coordinate { constructor(readonly x: number, readonly y: number) {} } const Up = new Coordinate(0, -1); const Right = new Coordinate(1, 0); const Down = new Coordinate(0, 1); const Left = new Coordinate(-1, 0); // How can we restrict the directio ...

Creating a Typescript interface for a anonymous function being passed into a React component

I have been exploring the use of Typescript in conjunction with React functional components, particularly when utilizing a Bootstrap modal component. I encountered some confusion regarding how to properly define the Typescript interface for the component w ...

When you make changes to a temporary object in Angular 2, those changes are also reflected in the main

I am currently working with two types of objects: Main Object - Customers (contains a list of customers, each with basic customer details) Temporary Object - Customer (holds the details of a specific customer selected by the user on the UI) Oddly enough ...

Tips for adjusting the time format within Ionic 3 using TypeScript

I currently have a time displayed as 15:12:00 (HH:MM:SS) format. I am looking to convert this into the (3.12 PM) format. <p class="headings" display-format="HH:mm" > <b>Time :</b> {{this.starttime}} </p> In my TypeScript code t ...

Angular Migration - Unable to locate a suitable version

I need to upgrade my application from Angular 10 to Angular 11. However, during the migration process, I encountered the following error: npm ERR! code ETARGET npm ERR! notarget No matching version found for @ruf/<a href="/cdn-cgi/l/email-protection" cl ...

Monitor changes in input display within ngIf statements

Within my code, I am utilizing an input element within a conditional statement of *ngIf: <div *ngIf='display'> <input number="number" /> </div> My goal is to be able to detect the visibility state of the input element insi ...

Tips for hiding a <div> styled as a tooltip in an Angular application when the user clicks elsewhere

I am currently developing an Angular 7 application. One of the features I have implemented is an interactive icon that reveals an absolutely positioned tooltip component when clicked on by the user. However, I am faced with the challenge of making the too ...