How to access the component instance in Angular through router events

I am currently working on incorporating a title service into my Angular 10 application. My goal is to subscribe to router events, access the activated route's component, check if it has a title() getter, and then use that information to set the page's title. It seems like a simple task...

This is the code snippet I have in place:

    this.router.events
      .pipe(
        filter((event) => event instanceof NavigationEnd),
        map(() => this.rootRoute(this.route)),
        filter((route: ActivatedRoute) => route.outlet === "primary"),
        filter(
          (route: ActivatedRoute) =>
            ComponentWithTitleBase.isPrototypeOf(route.component as any)
        ),
        map((route) => (route.component as unknown) as ComponentWithTitleBase),
        tap(console.dir)
      )
      .subscribe((comp: ComponentWithTitleBase) => {
        this.titleSvc.title = comp.title;
      });

However, I keep running into an issue where comp.title is always undefined, even though the component does include a get title() getter:

export class AboutComponent extends ComponentWithTitleBase implements OnInit {
  get title(): string {
    return "About the demo";
  }

  ...
}

When I look at the output from console.dir, I can see AboutComponent. Can anyone help me figure out what is going wrong here?

Answer №1

According to the suggestion by @yurzui, one way to achieve this is by creating a directive:

custom-directive.component.ts

@Directive({
  selector: 'router-outlet'
})
export class CustomDirective {

  constructor(r: RouterOutlet, titleService: TitleService) {
    r.activateEvents.pipe(
      // takeUntil(r.destroyed),
    ).subscribe(compInstance => compInstance.title && titleService.setNewTitle(compInstance.title))
  }

  ngOnDestroy () {
    // destroyed.next;
    // destroyed.complete();
  }
}

title.service.ts

@Injectable({
  providedIn: 'root'
})
export class TitleService {

  private source = new Subject<string>();

  setNewTitle (t: string) {
    this.source.next(t);
  }

  constructor() { this.initializeSubscription() }

  private initializeSubscription () {
    this.src.pipe(
      /* ... */
    ).subscribe(title => {
      console.log('new title', title);
    })
  }
}

Check out ng-run demo.

Answer №2

There seems to be a slight misunderstanding here. When you use console.dir on the .component, you will not get an actual instance of AboutComponent, but rather its class. Therefore, if you want to access it as component.title, your getter should be static.

static get title(): string {
  return "About the demo";
}

Answer №3

Utilizing the @bespunky/angular-zen library enables you to achieve the following:

Incorporate the following code in the template containing the router outlet:

<router-outlet publishComponent></router-outlet>

Then, within the component requiring access to the instance:

import { Component     } from '@angular/core';
import { NavigationEnd } from '@angular/router';
import { RouteAware    } from '@bespunky/angular-zen/router-x';

@Component({
    selector   : 'app-demo',
    templateUrl: './demo.component.html',
    styleUrls  : ['./demo.component.css']
})
export class DemoComponent extends RouteAware
{
    protected onNavigationEnd(event: NavigationEnd): void
    {
        const currentInstance = this.componentBus.instance();

        console.log(`Navigation ended. Current component instance:`, currentInstance )
    }
}

This library is accessible as open-source and can be installed using the command below:

npm install @bespunky/angular-zen

For a more detailed demonstration, check out this live example.

💡 Should your router outlet have a specific name, you can specify it when using the instance() method to retrieve the relevant outlet's component.

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

I am unable to utilize the outcome of a custom hook within a function or within an effect hook

I've developed a unique custom hook that retrieves a list of individuals File: persons.hooks.ts import {useEffect, useState} from "react"; import Person from "../../models/person/Person"; const usePersons = () => { const ...

Using TypeScript to define task invocation parameters with AWS CDK's CfnMaintenanceWindowTask

Currently, I am utilizing AWS CDK along with the library @aws-cdk/aws-ssm and TypeScript to construct CfnMaintenanceWindowTask. The code example I am working on is derived from AWS CloudFormation documentation, specifically for "Create a Run Command t ...

The property '.....' is missing an initializer and has not been explicitly assigned in the constructor

I want to address an issue with a similar question title that was asked 5 years ago on Stack Overflow. The problem is related to declaring a variable as an array of a specific object type in an Angular component using TypeScript 4.9. Even though I tried t ...

Guide to creating JSDoc for a TouchEvent handler

Looking to improve my shorter-js codebase with JSDoc for TypeScript definitions, but hitting a roadblock. I've implemented the on() function using Element.addEventListener, working well so far. However, when passing a TouchEvent as a parameter for an ...

The Typescript compiler will continue to generate JavaScript code even if there are compilation errors

As a fresh learner of TypeScript, I have been experimenting with some basic concepts. Below is the code from my file app1.ts: class Monster { constructor(name, initialPosition) { this.name = name; this.initialPosition = initialPosition ...

Verify an entry with exactly 7 numerical digits

When inputting data, the user is limited to entering only 7 figures. If more than 7 figures are entered, an error message will display: "You need 7 digits". For instance, if the user enters something like this: 12345678910 The error message is correctly ...

What could be causing the issue of Vuejs 3.3 defineModel consistently returning undefined?

I am currently working with Nuxt version 3.5.1 and Vuejs version 3.3, however, I am encountering an issue where the defineModel macro always returns undefined. I am unsure why this is happening? <template> <input v-model="count"& ...

Encountering a problem during npm installation on Windows 10 while trying to install the Angular CLI globally using the

node -v v4.5.0 npm -v 5.0.1 Is there anybody who encountered a similar problem when trying to install angular-cli on Windows 10? ...

Leveraging typegoose in a multitenant environment within the nestjs framework

I am looking to implement multitenancy functionality where each tenant will have its own database. Can Typegoose dynamically create connections for this purpose? ...

The message "The property 'layout' is not found on the type 'FC<WrapperProps>' in Next.js" is displayed

I encountered an error in my _app.tsx file when attempting to implement multiple layouts. Although the functionality is working as expected, TypeScript is throwing an error Here is the code snippet: import Layout from '@/components/layouts&apo ...

Transition from using ReactDOM.render in favor of asynchronous callback to utilize createRoot()

Is there a React 18 equivalent of this code available? How does it handle the asynchronous part? ReactDOM.render(chart, container, async () => { //code that styles some chart cells and adds cells to a worksheet via exceljs }) ...

Efficient methods to transfer values or arrays between components in Angular 8 without relying on local storage

I am working on a project that involves two components: a login component and a home component. I need to pass user data from the login component to the home component without using local storage. Is there a way to achieve this in Angular 8? Below is the ...

Using Jest and TypeScript to mock the return value of react-oidc-context

For our project, we utilize react-oidc-context to handle user authentication using oidc-client-ts under the hood. The useAuth function provided by react-oidc-context gives us access to important information such as isAuthenticated, isLoading, and the auth ...

What strategies can be employed to manage developer data input into components using ESLint?

In the midst of creating a design system that can be seamlessly integrated into any Angular library, I find myself faced with the challenge of implementing error and warning messages for developers using the system. Specifically, I want to ensure that if i ...

What is the process for obtaining an HTML form, running it through a Python script, and then showcasing it on the screen

I am inquiring about the functionality of html and py script. .... The user enters 3 values for trapezoidal data from the html form: height, length of side 1, and length of side 2, then clicks submit. The entered values are then sent to be calculated using ...

What is the best way to implement multiple templates for a single component?

Is there a way to configure my Home Component based on the user's role? For instance: If the employee is an admin, then the home component should load the template URL designed for admins. Likewise, if the employee is a cashier, then the home compo ...

Having difficulty converting string columns/data to numerical values when exporting an Ag-Grid table to Excel with getDataAsExcel function

I am having an issue with exporting data from my ag-grid table to excel using the API method getDataAsExcel. The problem arises because I have a column containing only string values, while all other columns are numeric and displayed in the ag-grid table a ...

Encountering errors in Typescript build due to issues in the node_modules directory

While running a typescript build, I encountered errors in the node_modules folder. Despite having it listed in the exclude section of my tsconfig.json file, the errors persist. What's puzzling is that another project with identical gulpfile.js, tsconf ...

The image will not appear until the Angular code has been recompiled or the server has been rebooted

I'm at a loss... Scenario An Angular application spanning 2 pages: one page for listing pictures (stored in "assets/picture" directory) one page for uploading pictures, posting them to a node/express API responsible for moving the pictures into th ...

Error in Django framework: Attempting to insert a null value in the "hardware_type" column violates the not-null constraint

I have encountered a problem for which I have found solutions on Stack Overflow, but unfortunately, they do not work in my specific case. Here is a snippet of my code: models.py hardware_used = models.CharField(max_length=20, blank=True, null=True) core ...