0

I am trying to call a method in one component from other component using injectable service

My first component (I'm calling method in other component from this component)

bottombar.component.ts

import { Component, ElementRef, OnInit, ViewChild, AfterViewInit, ChangeDetectorRef, EventEmitter, Input, Output } from "@angular/core";
import { Router } from "@angular/router";
import { Label } from "ui/label";
import { BottomBarService } from '../../services/bottombarservice/bottombar.service';

@Component({
  selector: "bottom-bar",
  templateUrl: "./components/bottombar/bottombar.html",
  styleUrls:["./components/bottombar/bottombar-common.css", "./components/bottombar/bottombar.css"],
  //providers: [BottomBarService]
})

export class bottombarComponent implements OnInit {

  constructor(private bottomBarService: BottomBarService) {

  }

  openDrawer(){
    this.bottomBarService.callSideDrawerMethod();
  }
  ngOnInit() {}


}

From the above component I'm trying to call a method in SideDrawerGettingStartedComponent which is present below which will trigger a method that opens side drawer

My Second component (In which the called method is present)

sidedrawer.component.ts

import { Component, ViewChild, OnInit, AfterViewInit, ChangeDetectorRef } from "@angular/core";
import { Page } from "ui/page";
import { ActionItem } from "ui/action-bar";
import { Observable } from "data/observable";
import { RadSideDrawerComponent, SideDrawerType } from "nativescript-telerik-ui-pro/sidedrawer/angular";
import { RadSideDrawer } from 'nativescript-telerik-ui-pro/sidedrawer';
import { BottomBarService } from '../../services/bottombarservice/bottombar.service';

@Component({
    // moduleId: module.id,
    selector: "tk-sidedrawer-getting-started",
    templateUrl: "./components/sidedrawer/sidedrawer.html",
    styleUrls: ['./components/sidedrawer/sidedrawer.css'],
    //providers: [BottomBarService]
})
export class SideDrawerGettingStartedComponent implements AfterViewInit, OnInit {
    private _mainContentText: string;

    constructor(private _changeDetectionRef: ChangeDetectorRef,private bottomBarService: BottomBarService) {
      this.bottomBarService.sideDrawerMethodCalled$.subscribe(() => {
        console.log("subscribed")
        alert("hello")
        this.openDrawer()
      })
    }

    @ViewChild(RadSideDrawerComponent) public drawerComponent: RadSideDrawerComponent;
    private drawer: RadSideDrawer;

    ngAfterViewInit() {
        this.drawer = this.drawerComponent.sideDrawer;
        this._changeDetectionRef.detectChanges();
    }

    ngOnInit() {
        this.mainContentText = "SideDrawer for NativeScript can be easily setup in the HTML definition of your page by defining tkDrawerContent and tkMainContent. The component has a default transition and position and also exposes notifications related to changes in its state. Swipe from left to open side drawer.";
    }

    get mainContentText() {
        return this._mainContentText;
    }

    set mainContentText(value: string) {
        this._mainContentText = value;
    }

    public openDrawer() {
        console.log("triggered openDrawer in main component")
        this.drawer.showDrawer();
    }

    public onCloseDrawerTap() {
       this.drawer.closeDrawer();
    }
}

And Shared service is as below

bottombar.service.ts

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

@Injectable()
export class BottomBarService{
    private sideDrawerMethodSource = new Subject<any>();
    sideDrawerMethodCalled$ = this.sideDrawerMethodSource.asObservable();

    callSideDrawerMethod(){
        console.log("Inside service bottomBar")
        this.sideDrawerMethodSource.next(null);
        console.log("after")
    }
}

Problem

I have an html associated with bottombar.component.ts which contains a button. On tap it will trigger openDrawer() function in bottombar.component.ts

I can see the consoled value in my service file, but somehow it is not triggering the subscribe in sidedrawer.component.ts

There is no error and because of that it is difficult to find what is exactly causing the issue.

Also I have declared my service in ngModule's provider to avoid singleton issue.

Is there something that I'm missing here?

Thanks in advance

Yeshwanth
  • 70
  • 8
  • Possible duplicate of [Angular - shared service between components doesn't work](https://stackoverflow.com/questions/43997489/angular-shared-service-between-components-doesnt-work) – eko Jun 15 '17 at 10:58
  • I tried that solution which is declaring service in `ngModule` as I mentioned in last lines, It is not working even after providing the service at the root – Yeshwanth Jun 15 '17 at 11:03
  • 2
    Read the answer carefully, you still re-provided your service inside your `@Component` annotation – eko Jun 15 '17 at 11:06
  • Are you sure that your `sidedrawer` component is loaded? – Amit Chigadani Jun 15 '17 at 11:08
  • @echonax I have overlooked the answer, I changed the code according to the your solution by providing only in `ngModule` . Still I don't get the console values in **sidedrawer.component.ts** component. I have upated the answer too . – Yeshwanth Jun 15 '17 at 11:16
  • @AmitChigadani Yes, because I didn't getting any errors while importing it. – Yeshwanth Jun 15 '17 at 11:18
  • @Yeshwanth why are you not using `EventEmitter` ? – Abrar Jun 15 '17 at 11:20
  • My question is whether `sidedrawer` constructor is executed at least once or not? Try to log before doing subscribe and check. – Amit Chigadani Jun 15 '17 at 11:38
  • 1
    @Abrar `EventEmitter` is suitable only when two components have `parent-child` relationship. – Amit Chigadani Jun 15 '17 at 11:39
  • @Yeshwanth, ya my mistake. I wrote a solution below – Abrar Jun 15 '17 at 11:43
  • @AmitChigadani u r right, I tried to console a value before subscribing, even that is not coming up. What could be the reason? – Yeshwanth Jun 15 '17 at 11:44
  • Seems that ` ` component is never triggered from the html template or it is blocked by some condition. – Amit Chigadani Jun 15 '17 at 11:47

2 Answers2

0

It seems you missed to append '$' next to sideDrawerMethodCalled

Try below code:

callSideDrawerMethod(){
        console.log("Inside service bottomBar")
        this.sideDrawerMethodSource$.next(null);
        console.log("after")
    }
Suneet Bansal
  • 2,664
  • 1
  • 14
  • 18
  • my variable in line private `sideDrawerMethodSource = new Subject();` doesn't have the `$`. So I didn't use it that way. Anyways I tried appending `$`, still its not working – Yeshwanth Jun 15 '17 at 10:59
0

In your shared service, instead of passing null here this.sideDrawerMethodSource.next(null), you can pass a status:boolean. In your bottombar.service.ts -

callSideDrawerMethod(status:boolean){
    this.sideDrawerMethodSource.next(status);
}

Now, in the bottombar.component.ts, pass a status when invoking the method -

this.bottomBarService.callSideDrawerMethod(true);

In your sidedrawer.component.ts, pass a status param -

  this.bottomBarService.sideDrawerMethodCalled$.subscribe((status) => {
        console.log("subscribed")
        alert("hello")
        this.openDrawer()
      })

And instead of subscribing in the constructor, place the code in ngOnInit() life cycle hook.

Hope this helps.

Abrar
  • 6,874
  • 9
  • 28
  • 41