1
votes

I'm using query params to navigate to a specific tab between components. The receiving component (which needs to check the query params) keeps returning the error:

Cannot set property active of undefined

In one component, I have the following html.

<button *ngIf="isLoggedInUser" style="position: absolute; right: 0" class="btn btn-link btn-sm"
            [routerLink]="['/users/' + auth.currentUser.id + '/edit']" [queryParams]="{tab: 2}">
            <i class="fas fa-pen"></i>
</button>

In the edit component (the one checking the query params), I have this in my ngOnInit using ActivatedRoute.

this.router.queryParams.subscribe(params => {
  const selectedTab = params["tab"];
  console.log(this.editProfileTabs);
  this.editProfileTabs.tabs[
    selectedTab > 0 ? selectedTab : 0
  ].active = true;
});

When I try it...i get this in the console:

core.js:1673 ERROR TypeError: Cannot set property 'active' of undefined

any ideas? I would think the ternary would handle null/undefined stuff.

I've console logged the tabset and it does log tabs in that html group.

enter image description here

2
Check the content of this.editProfileTabs, this probably doesn't have values the index you are trying to fetch.Ashish Ranjan
Good idea. I did. Console shows tabs. See updated post with screenshot.J.G.Sable
Problem with this debugging is, console logs are lazy and evaluated late. Under queryParams subscription, try logging like: console.log(JSON.parse(JSON.stringify(this.editProfileTabs))).Ashish Ranjan
ah. Yes. Now there are only 2 tabs in the tabset array at indexes 0 & 1. So index 2 doesn't exist. Ideas on how to fix?J.G.Sable
But still, follow the first suggestion if it applies. setTimeout() calls change detection for the whole app while a detectChanges() will call only for the current component and its children.Ashish Ranjan

2 Answers

2
votes

Reference variables are loaded into the component in under ngAfterViewInit() life cycle hook. So if you are accessing it in your ".ts" then do it under ngAfterViewInit().

ngAfterViewInit() {
    this.router.queryParams.subscribe(params => {
        this.editProfileTabs.tabs[selectedTab > 0 ? selectedTab : 0].active = true;
    });
}

In the development mode, angular does two checks so if you change property which is bound to HTML under ngAfterViewInit() then you in the second check you will be getting errors like:

ExpressionChangedAfterItHasBeenCheckedError

To fix this, you should run change detection manually. Inject ChangeDetectorRef in the component and use it like:

constructor(private _cdr: ChangeDetectorRef) {
    .....
}

ngAfterViewInit() {
    this.router.queryParams.subscribe(params => {
        this.editProfileTabs.tabs[selectedTab > 0 ? selectedTab : 0].active = true;
        this._cdr.detectChanges()
    });
}
0
votes

For me worked this code

ngAfterViewInit() {    
    this.route.queryParams.subscribe(params => {
        const selectedTab = params["tab"];
        this.editProfileTabs.selectedIndex = selectedTab > 0 ? selectedTab : 0;
    });
}