theHeman
theHeman

Reputation: 505

How to make components in Angular 2 singleton?

I am using Angular 2 to build my web application which which has lot of components. I am using angular-cli to create, run and build the project.
Accidentally (or luckily) I stumbled across a bug where I realized that multiple instances of my component were being created. Even worse was when I realized that my code was referring to any one this instances randomly without any logic to trace it back.

As an example, check the following scenario:

This is the image of my log statement. I have blackened out the sensitive parts. It can be clearly seen that some rest calls are being made with the unique id for tenant 1 while some for trial tenant. Also use of two instances is also very clear from two instance times. The old instance of previous logged in tenant is somehow still in play and my component is still able to access it.

My Questions are:

  1. Is there a way to make the component class singleton?
  2. Is there any way to destroy the component instance on leaving the component?

Upvotes: 10

Views: 14539

Answers (4)

Pascal Fournier
Pascal Fournier

Reputation: 33

Zion Bokobza's answer helped me but that Main1Component.lastComp = this; ought to be in the onInit not in the onDestroy, or else lastComp will remain null until the component is destroyed:

      ngOnInit(): void {
        if (!Main1Component.lastComp) {
          this.name = 'Zion';
          Main1Component.lastComp = this;
        }
      }

Upvotes: 0

Zion Bokobza
Zion Bokobza

Reputation: 91

I had the same problem when I add to define a tab which every time I choose one of the tab, it creates the component instead of using the last created one. My solution works for a simple components, and I am not sure that this solution is the right one but it worked for me as I said in a simple components.

Here is the code of the component which I want to have only one - like singleton

import { Component, OnInit, OnDestroy } from '@angular/core';

@Component({
  selector: 'app-main1',
  templateUrl: './main1.component.html',
  styleUrls: ['./main1.component.scss']
})
export class Main1Component implements OnInit, OnDestroy {

  static lastComp: Main1Component;

  constructor() {
    if (Main1Component.lastComp) {
      return Main1Component.lastComp;
    }
   }


  name: string;
  ngOnInit(): void {
    if (!Main1Component.lastComp) {
      this.name = 'Zion';
    }
  }

  ngOnDestroy(): void {
    Main1Component.lastComp = this;
  }
}

I am keeping the last created component in a static member and in the constructor if the static exist I use it instead of creating one. I am doing OnInit only once! In Destroy I keep the last one in the static member.

I hope it will help someone, will be glad to get any remark on this.

Upvotes: 3

user12047560
user12047560

Reputation: 1

Well I can identify with the need to have a component as a singleton because a service cannot have html, and you sometimes need to associate the html to be part of the singleton instance. But YOU CAN in-fact make a component a singleton:

private static _counter = 0;
static CountInstances() : Boolean {
  ++SingletonComponent._counter;
  if(SingletonComponent._counter > 1){
    return false;
  }
  return true;
}

if(!SingletonComponent.CountInsances()) //throw error and stop app from running

Upvotes: 0

bresleveloper
bresleveloper

Reputation: 6066

  1. Is there a way to make the component class singleton?

not that i am aware of

  1. Is there any way to destroy the component instance on leaving the component?

yes, there is an interface OnDestroy

export class ClockComponent implements OnDestroy {
interval;

ngOnDestroy() {
  clearInterval(this.interval);
}

constructor() {
  this.interval = setInterval( ()=> console.log('tick') );
}

Upvotes: 2

Related Questions