Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 Global Variable across multiple component instances

Tags:

angular

I have two components on one page: Component1 and Component2. Inside each of those is Component3. Obviously each Component 3 is its own instantiation of the component. However, I would like a global variable between the two. I'm creating a side-by-side comparison of some data, and would like an accordion to work, so when I click to expand the accordion on one Component 3, the other one also opens. I have been searching for hours and cannot find a resolution to this.

What I want is, for instance:

(click) = "changeGlobalVar()"

to change the global variable. Then I would like to have

*ngIf="globalVar"

That way, the ngIf works on both Component 3, no matter which one I click on.

Could someone please help me out? I've been searching for an answer to this for hours.

Here's what my service code looks like but doesn't seem to be working:

import {Injectable} from '@angular/core';

@Injectable()
export class DropDownService {

  public _acDropDownToggle: boolean;

  setValue(val) {
    this._acDropDownToggle = val;
  }

  getValue() {
    return this._acDropDownToggle;
  }

}
like image 257
Chris Stanley Avatar asked Dec 11 '22 15:12

Chris Stanley


2 Answers

So you are half way there and you need just a few clarifications on how to leverage a service. The service you create should only be inserted as a "provider" in your main component. All child components will use the service as a "Dependency injection", this means the child components will request the service in their constructor method arguments.

For example your primary component will look like this

import {componentStateService} from './componentState.service'
import {ComponentOne} from './component1'
import {ComponentTwo} from './component2'
@Component({
    selector: 'test-app',
    template : `...`,
    providers: [componentStateService],<----
    directives: [ComponentOne,ComponentTwo]
})
export class AppComponent {
    constructor(){}
}

Then the child components (component-one,component-two in my plunker example. For your code you would only apply this to your third component), will have the service injected in through their constructors.

import {componentStateService} from './componentState.service'
@Component({
    selector: 'component-one',
    template : `...`
})
export class ComponentOne extends OnInit {
    private _componentVisible:boolean;
    constructor(private _componentStateService:componentStateService){<----
        this._componentVisible = true;
    }
}

This will ensure that only one instance of your service is created.


The next step is to add an "observable" to your service and then "subscribe" to that observable in your child components.

Here is a plunker that demonstrates exactly what you are looking for. You will need to use the RxJS modules. The plunker shows you how to add this if you are using SystemJS. If you are using the TypeScript compiler to transpile your .ts to .js, you will also need to install RxJS through npm(In the plunker example SystemJS is using a module to transpile).

A good tutorial on Angular 2 Observables can be found here. The tutorial leverages a lot more features than what I use in the plunker but that should be enough to get you started.

like image 85
Dan Simon Avatar answered Jan 01 '23 13:01

Dan Simon


Since the variable ind DropDownService is to be shared between two instances of component 3, the best place to instantiate it would be in the page component.Page Component will be the lowest common ancestor of the two component3 instances

Assuming your component tree is like this :-

             PageComponent
             /          \
            /            \
     Component1          Component2
        /                    \
       /                      \
   Component3                Component3

The best place to provide DropDownService in the providers array will be in the Component Decorator of PageComponent. You should then just inject it in the constructor of Component3. If you specify the service in provider of any of the child components of the Pagecomponent, a new instance will be created again.

like image 27
Krishnanunni Jeevan Avatar answered Jan 01 '23 15:01

Krishnanunni Jeevan