0

I have to 2 component LeftPanelComponent and RightPanelComponent. I referred this code for my implementation

I created one shared service between two component to call abc() function of RightPanelComponent from LeftPanelComponent.

I'm reading value from ListDialogComponent into LeftPanelComponent and passing to abc() function.

abc() function of RightPanelComponent is calling successfully from LeftPanelComponent.

But when I'm calling saveCustomData() angular 2 service in abc() function then I'm getting following error.

EXCEPTION: Error in ./ListDialogComponent class ListDialogComponent - inline template:29:6 caused by: Cannot read property 'saveCustomData' of undefined

LeftPanelComponent.ts

import { Component, OnInit } from '@angular/core';
import {LeftpanelService} from "../leftpanel.service"
import {Leftpanel} from "../leftpanel";
import {MdDialog} from "@angular/material";
import {MdDialogRef} from "@angular/material";
import {ListDialogComponent} from "../list-dialog/list-dialog.component";
import {SharedService} from '../shared-service/shared-service.component';
@Component({
 selector: 'app-leftpanel',
 templateUrl: './leftpanel.component.html',
 styleUrls: ['./leftpanel.component.css']
})
export class LeftpanelComponent implements OnInit {
 dialogRef: MdDialogRef<any>;
 leftpanels:Leftpanel[];

 constructor(public dialog: MdDialog,private service:LeftpanelService, private sharedService: SharedService) {

 }

 ngOnInit() {
   this.service.getLeftpanels().subscribe(lst =>this.leftpanels=lst);
 }

 transferDataSuccess($event) {
   this.receivedData.push($event.dragData);
   this.openDialog();
 }
 openDialog() {
  this.dialogRef.afterClosed().subscribe(result => {
   console.log('result: ' + result);
   this.dialogRef = null;
   this.sharedService.componentOneFn(sessionStorage.getItem("value"));
  });
 }
 }

ListDialog.Component.html

<form class="form-group" >
<select name="itemid" #selectedCategory class="selectOption">
  <option value="">Choose Item</option>
  <option *ngFor="let Item of Items" value="{{Item.id}}" >{{Item.name}}</option>
</select>
<p></p>
<button  type="button" (click)="dialogRef.close('yes',getValueFromSelect(selectedCategory.value))" class="btn">Submit</button>
<button  type="button" (click)="dialogRef.close('no')" class="btn">Cancel</button>
</form>

ListDialogComponent.ts

import { Component,OnInit} from '@angular/core';
import {MdDialogRef} from "@angular/material";
import {Item} from '../item';
import {GetListService} from '../get-list.service';
@Component({
 selector: 'app-list-dialog',
 templateUrl: './list-dialog.component.html',
 styleUrls: ['./list-dialog.component.css']
})
export class ListDialogComponent implements OnInit {
 Items : Item[];
 serverItemID : string;
 constructor(public dialogRef: MdDialogRef<ListDialogComponent>,private service:GetListService) { }

 ngOnInit() {
  this.service.getItemList(this.oauthTokenService.getHeaders()).subscribe(lst =>this.Item=slst);
 }

 getValueFromSelect(value){
  sessionStorage.setItem('value',value);
 }
}

RightPanelComponent.ts

import {SaveCustomItem} from '../save-custom-item';
import {SaveCustomService} from '../save-custom.service';
import {SharedService} from '../shared-service/shared-service.component';

@Component({
 selector: 'app-rightpanel',
 templateUrl: './rightpanel.component.html',
 styleUrls: ['./rightpanel.component.css']
})
export class RightpanelComponent implements OnInit {
 componentData = [];
 componentData2 = [];
 saveCustomItems:saveCustomItem[];


constructor(public dialog: MdDialog, private service:SaveCustomService, private sharedService: SharedService) {
this.sharedService.componentOneFn = this.abc;
}
abc(value) {
 if(value == "MyValue") {
   this.service.saveCustomData(value).subscribe(lst =>this.saveCustomItems=lst);
 }
}
}

SharedService.ts

import {Injectable} from '@angular/core';
@Injectable()
export class SharedService {

 componentOneFn: Function;

 constructor() { }
}

SaveCustomService.ts

import { Injectable } from '@angular/core';
import {Http, Response, Headers} from "@angular/http";
import {Observable} from "rxjs/Rx";
import 'rxjs/Rx';
import {AppSettings} from './appsettings';
import {SaveCustomItem} from './save-custom--item';

@Injectable()
export class SaveCustomService {

  constructor(private http:Http) { }

  saveCustomData(value):Observable<SaveCustomItem[]> {
    let response = this.http.get(`${AppSettings.BACK_ENDPOINT}/ajax/save-custom-data?value=`+value);
    let saveCustomItems = response.map(mapSaveCustomData);
    return saveCustomItems;
  }
}

function mapSaveCustomData(response:Response):SaveCustomItem[] {
 return response.json().results.map(toSaveCustomData);
}

function toSaveCustomData(r:any):SaveCustomItem {
 let saveCustomeItem = <SaveCustomItem>({
   id:r.server,
   title:r.title
 });
 return saveCustomeItem;
}
Community
  • 1
  • 1
Anil Jagtap
  • 1,740
  • 4
  • 27
  • 44

2 Answers2

3

In SaveCustomService you are declaring your methods outside the class clousure bracket }.

Should be like this:

@Injectable()
export class SaveCustomService {

    constructor(private http: Http) {
    }

    saveCustomData(value): Observable<SaveCustomItem[]> {
        let response = this.http.get(`${AppSettings.BACK_ENDPOINT}/ajax/save-custom-data?value=` + value);
        let saveCustomItems = response.map(mapSaveCustomData);
        return saveCustomItems;
    }

    mapSaveCustomData(response: Response): SaveCustomItem[] {
        return response.json().results.map(toSaveCustomData);
    }

    toSaveCustomData(r: any): SaveCustomItem {
        let saveCustomeItem = <SaveCustomItem>({
            id: r.server,
            title: r.title
        });
        return saveCustomeItem;
    }
}

Edit:

Cannot read property 'saveCustomData' of undefined

Means that this.service in this.service.saveCustomData is undefined.

So, I think that you should check and be certain that ../shared-service/shared-service.component in your import is the correct path.

Also remember to add SharedService in your module's providers:

@NgModule({
    providers: [SharedService]

Edit2:

Just a tip. You can create 1 service for a conceptual block or scope. And use it to pass data between components that share the same conceptual block or scope.

In the documentation: https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service , you see how it is used 1 service to pass data from Mission Component to Astronaut Component, they both belong to one conceptual block: 'Astronaut performing mission'.

Same thing would be applied to these more common conceptual scopes: 'Users', 'Orders', 'Payments', and so on.

You don't need to create a service A to call a method of service B. Call directly service B.

SrAxi
  • 19,787
  • 11
  • 46
  • 65
  • Thank you for your response. But your answer not working. – Anil Jagtap Apr 12 '17 at 10:07
  • @AnilJagtap Check edit in my answer. I will keep looking to see if I find any other reason for the error. – SrAxi Apr 12 '17 at 10:10
  • I already Kept sharedService in providers. Still have problem. What I need to do? – Anil Jagtap Apr 12 '17 at 10:11
  • @AnilJagtap Did you also add `SaveCustomService` to `providers`? Make sure to add all your services to `providers` in the component's module. – SrAxi Apr 12 '17 at 10:13
  • @AnilJagtap Friend, where are you actually calling `abc()`? – SrAxi Apr 12 '17 at 10:30
  • I'm calling abc() function in LeftPanelComponent using SharedService.ts. Can we call abc() from LeftPanelComponent directly without creating shared service? – Anil Jagtap Apr 12 '17 at 10:32
  • I don't see you calling `abc()`, I see you calling `componentOneFn()` in `LeftPanelComponent` component. Anyway, you can add X service to your component's module `providers`, instance it in your `constructor` and then call methods within that X service. Usually you want to create 1 service for a conceptual block, Example: `UserService` will be 1 service called in `UserViewComponent`, `Top5Users` and `UserDetails`. This way, `UserService` will be used to pass information from one component to another. You don't need to create so many services, keep it in conceptual, if you know what I mean. – SrAxi Apr 12 '17 at 10:41
  • @AnilJagtap I tried to explain here my view on services and it's usage. Check second Edit of my answer bro! ;) – SrAxi Apr 12 '17 at 10:46
  • I did same way whatever you explained here. I'm abc() from LeftPanelComponent using Shared service. abc() function is calling fine but not executing service. why? saveCustomeData service executing in same component but not executing in abc() function. – Anil Jagtap Apr 12 '17 at 10:48
  • @AnilJagtap I only see `abc()` being declared in `RightPanelComponent`. I don't see where it is called. If it is called in a `.html` template you should post it. – SrAxi Apr 12 '17 at 10:58
  • I created SharedService. which is created communication bridge into Left and Right Panel Component. From left panel I'm calling shared service this.sharedService.componentOneFn(sessionStorage.getItem("value")); and in right panel constructor i'm calling abc() llike: this.sharedService.componentOneFn = this.abc; – Anil Jagtap Apr 12 '17 at 11:03
0

I resolved my problem. I did some modification in SharedService, LeftPanelComponent, and RightPanelComponent.

SharedService.ts

import {Injectable} from '@angular/core';
@Injectable()
export class SharedService {

// Observable string streams
componentMethodCalled$ = this.componentMethodCallSource.asObservable();

// Service message commands
callRightPanelComponentMethod() {
 this.componentMethodCallSource.next();
}
}

RightPanelComponent.ts

import {SaveCustomItem} from '../save-custom-item';
import {SaveCustomService} from '../save-custom.service';
import {SharedService} from '../shared-service/shared-service.component';

@Component({
 selector: 'app-rightpanel',
 templateUrl: './rightpanel.component.html',
 styleUrls: ['./rightpanel.component.css']
})
export class RightpanelComponent implements OnInit { 
 saveCustomItems:saveCustomItem[];

 constructor(public dialog: MdDialog, private service:SaveCustomService, 
  private sharedService: SharedService) {
  this.sharedService.componentMethodCalled$.subscribe(
    () => {
    this.abc();
    }
  );
 }
 abc(value) {
   if(value == "MyValue") {
     this.service.saveCustomData(value).subscribe(lst =>this.saveCustomItems=lst);
 }
 }
 }

RightPanelComponent.ts

openDialog() {
 this.dialogRef.afterClosed().subscribe(result => {
  console.log('result: ' + result);
  this.dialogRef = null;
  this.sharedService.callRightPanelComponentMethod();
 });
}
Anil Jagtap
  • 1,740
  • 4
  • 27
  • 44