pankaj malik
pankaj malik

Reputation: 107

Sharing data between components in Angular

getting issue in component data sharing. i have 2 components, they don't have parent child relationship. in my sidebar component i have a checkbox, by clicking this checkbox i want to perform some action in my dashboard component.

sidebar component

  manageWidgetLocation(){
  this.togglewidgetService.toggleSideNav(true);
  }

dashboard component

    ngOnInit(): void {
       this.togglewidgetService.onSideNavToggle()
        .subscribe(
         (opening) => {
                       debugger;
                       if (opening) {
                          console.log(">>>>>>>here");
                       } else {
                          //Logic to close the sidenav here
                        }
                   }
                );
            }

     open(sidenav) {
                  sidenav.open();
                                 }

    close(sidenav) {
              sidenav.close();
                               }

service

    import { Injectable } from "@angular/core"

    import { Observable, Subject } from "rxjs/Rx";

    @Injectable()
    export class toggleWidgetService {

      private sidenavOpenSubject : Subject<boolean>;

     constructor() {
       this.sidenavOpenSubject = new Subject<boolean>();
                                                        }

      toggleSideNav(opening: boolean): void {
      this.sidenavOpenSubject.next(opening);
                                            }

      onSideNavToggle(): Observable<boolean> {
       return this.sidenavOpenSubject;
                                          }

              }

Upvotes: 0

Views: 1147

Answers (3)

shubham agarwal
shubham agarwal

Reputation: 177

In service:

 Make observable of your sidenavOpenSubject variable as =>

    subject_observable = this.sidenavOpenSubject.asObservable();

In Dashboard Component:

Try to subscribe subject_observable as =>    

this.togglewidgetService.subject_observable.subscribe(   opening =>
  {
 // 
  } )

Upvotes: 0

John Velasquez
John Velasquez

Reputation: 3451

My best advice is to create a CoreModule that represents a single instance module, and create a pub/sub service to share data across your modules.

CoreModule

import {
    ModuleWithProviders, NgModule,
    Optional, SkipSelf } from '@angular/core';

//Providers
import { PubSubService } from './pub-sub.service';


/**
 * This module handles all the singleton services
 */
@NgModule({
    imports: [],
    exports: [],
    declarations: [],
    providers: [PubSubService]
})
export class CoreModule {
    constructor( @Optional() @SkipSelf() parentModule: CoreModule) {
        if (parentModule) {
            throw new Error(
                'CoreModule is already loaded. Import it in the AppModule only');
        }
    }

    static forRoot(): ModuleWithProviders {
        return {
            ngModule: CoreModule,
            providers: [PubSubService]
        };
    }
}

PubSubService

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';

/**
 * Publisher/Subscriber Service
 */
@Injectable()
export class PubSubService {

    private events: any = {};

    constructor() { }

    /**
     * Subscribes the instance of the assigned event name
     * @param eventName
     * Event name of the delegate
     */
    public On(eventName: PubSubEvents): Observable<any> {

        if (typeof this.events[eventName] === 'undefined') {
            this.events[eventName] = new Subject<any>();
        }

        return this.events[eventName].asObservable();
    }

    /**
     * Broadcast data to the specified event channel
     * @param eventName
     * Event name of the delegate
     * @param eventArgs
     * Arguments to pass through the connected channel
     */
    public Broadcast(eventName: PubSubEvents, eventArgs: any) {
        if (!this.events[eventName]) {
            return;
        }

        this.events[eventName].next(eventArgs);
    }





}

//Your events
export declare type PubSubEvents = "OnSideNavToggle" | "OnAnyOtherEvent1" | "OnAnyOtherEvent2";

How to use

Make sure CoreModule is only imported once, import it in AppModule

@NgModule({
    bootstrap: [ AppComponent ],
    imports: [
        CoreModule.forRoot(),
    ]
})
export class AppModule {

}

sidebar component

toggle: boolean = false;
constructor(private pubsub: PubSubService){

}

manageWidgetLocation(){
   this.boolean  = !this.boolean;
  this.pubsub.Broadcast("OnSideNavToggle", this);
}

dashboard component

constructor(private pubsub: PubSubService){
  this.pubsub.On("OnSideNavToggle").subscribe((res) =>{
    //res -> value of the toggle state
  });
}

Upvotes: 1

Carsten
Carsten

Reputation: 4208

service

@Injectable()
export class toggleWidgetService {
  sidenavOpenSubject: Subject<boolean> = new Subject<boolean>();
}

dashboard

constructor(private service: BlaService) {}

ngOnInit() {
  this.service.sidenavOpenSubject.subscribe(
    data => console.log(data),
    error => console.log(error)
  )
}

ngOnDestroy() {
  this.service.sidenavOpenSubject.unsubscribe()
}

sidebar

constructor(private service: Service) {}

someFunction() {
  this.service.sidenavOpenSubject.next(true);
}

this will work just fine.

Upvotes: 0

Related Questions