1

I'm new to Angular. I'm trying a simple thing today. I've gone through many answers but not able implement them correctly. I want to access some variables of filter-panel in filter-bar, (my two custom components). But none of the two is parent-child to each other. They're independent, though within the same directory. Here I've created a stackblitz. And here's my code:

filter-panel.component.ts

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

@Component({
    ...
})
export class FilterPanelComponent implements OnInit {

public activeFilters: string[];
public text: string="hello world";

constructor() {
    this.activeFilters = [
        'Apple',
        'Grapes',
        'Bana'
    ];
}

ngOnInit() {}

}

filter-bar.component.ts

import { Component, OnInit, ViewChild } from '@angular/core';
import { FilterPanelComponent } from './filter-panel/filter-panel.component';

@Component({
    ...
})
export class FilterBarComponent implements OnInit {

    @ViewChild('FilterPanelComponent', {static : false}) filterPanel: FilterPanelComponent;

    public values1: string[] = ['Philips'];

    public values2: string[];

    constructor() {
      //this.values2=this.filterPanel.activeFilters;  
    }

    ngOnInit() {
        //console.log(this.values2);
    }
}

After doing some more research I realized it's pointless to use @ViewChild in this scenario. So I tried making a service. I tried @Input(). I also tried this: How to use a variable from a component in another in Angular2. but I'm still not able to implement the solution. Please correct me.

Dimitar Spassov
  • 2,535
  • 2
  • 7
  • 17
Tanzeel
  • 4,174
  • 13
  • 57
  • 110
  • 1
    Does this answer your question? [How to share data between components using a service properly?](https://stackoverflow.com/questions/40468172/how-to-share-data-between-components-using-a-service-properly) – Kaustubh Khare Mar 06 '20 at 06:26
  • check this out https://fireship.io/lessons/sharing-data-between-angular-components-four-methods/ the last section "Unrelated Components: Sharing Data with a Service" – m_sultan Mar 06 '20 at 06:29
  • @KaustubhKhare, I can try that solution. But I'm not very well versed with services in angular. So that may take more time than it should. but sure, i'll give it a try. – Tanzeel Mar 06 '20 at 06:31
  • 1
    @Tanzeel check this link. **Any via a shared service** https://medium.com/@onejohi/sharing-data-between-components-in-angularjs-c34ff20b7fee – Kaustubh Khare Mar 06 '20 at 06:31
  • if you both component dont have parent child relationship and if you want to pass the data from one component to another component you can use `RxJs Subject` for the same – Yash Rami Mar 06 '20 at 06:32
  • 1
    I don't think you need any communication between components. You are just initializing properties of two components with an array of strings. Why don't you just save those values in a separate constant file and import it into both the components. – Jasdeep Singh Mar 06 '20 at 06:45
  • 1
    @Tanzeel, Can you look at my below solution, here I have passed ```this.activeFilters``` array from filter panel to filter bar component.. – Maniraj Murugan Mar 06 '20 at 07:15
  • Please let the OP know why his question was down voted. So that they'll be careful next time. I'm saying this in general. No personal grudges :-) – Tanzeel Mar 06 '20 at 10:12

2 Answers2

2

You can create a service to share the data between components,

A new service called, filter-panel.service.ts file with setter() and getter() method,

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

@Injectable()
export class FilterPanelService {

  filterdata: any[];
  constructor() { }

   get data(): any{
    return this.filterdata;
  }

  set data(val: any){
    this.filterdata = val;
    console.log(this.filterdata);
  }

}

In filter-panel.component.ts set the value like,

export class FilterPanelComponent implements OnInit {

    public activeFilters: string[];
    public text: string="hello world";

    constructor(public filterPanelService:FilterPanelService) {

        this.activeFilters = [
            'Provider: CMS',
            'Region: All',
            'Provider Group:All',
            'Provider: CMS',
            'Region: All',
            'Provider Group: All'
        ];

        this.filterPanelService.data = this.activeFilters;
    }

    ngOnInit() {}
}

And in filter-bar.component.ts get the value like,

export class FilterBarComponent implements OnInit {
    @ViewChild('FilterPanelComponent', {static : false}) filterPanel: FilterPanelComponent;


    public values1: string[] = ['Philips'];

    public values2: string[];


    constructor(public filterPanelService: FilterPanelService) {

      //this.values2=this.filterPanel.activeFilters;  
    }

    ngOnInit() {
        //console.log(this.values2);
        console.log('value received ', this.filterPanelService.data);
    }
}

Working Stackblitz..

Maniraj Murugan
  • 8,868
  • 20
  • 67
  • 116
  • This is what me and @Yash are trying to do. This solution worked. Let me please put this ins production and run some unit tests. I'll be back shortly. :-) – Tanzeel Mar 06 '20 at 07:17
  • 1
    @Tanzeel, I am not sure about the other solution by Yash.. But here I have provided you solution with working stackblitz which exactly what you want.. Also this is no way similar solution like that here I have used ```getters``` and ```setters``` method to share the data.. – Maniraj Murugan Mar 06 '20 at 07:20
  • @Tanzeel, No issues.. But I am not very sure about the accepted solution whether that is the solution you need because it share data when you click on the text ```Filter-panel working```.. – Maniraj Murugan Mar 06 '20 at 07:27
  • I accepted the solution because I wanted to see how service is created and used. From there I can handle things my way. :-) – Tanzeel Mar 06 '20 at 07:32
  • Also I can change my vote later. Because I've shared both the solutions to my tech lead. She'll do the code review. – Tanzeel Mar 06 '20 at 07:33
  • @Tanzeel, Really not an issue about that.. Its all your decision of accepting the solution at the end.. But I just said that you have not mentioned anywhere in question about share data on click of the text.. Okay anyhow glad to give a solution.. – Maniraj Murugan Mar 06 '20 at 07:33
  • 2
    @Tanzeel, I won't bother about votes or acceptance really.. At the end I need to help people to over come issue and not anything more in it.. – Maniraj Murugan Mar 06 '20 at 07:35
  • This answer is more useful than the previous one. Thus, I'm changing my vote. – Tanzeel Mar 06 '20 at 09:59
  • @Tanzeel,May I know the reason?? I am asking to know how people see my solution.. So Whether my solution passed your test cases and your team gets satisified?? I would like to know the feedback over this solution.. – Maniraj Murugan Mar 06 '20 at 10:01
  • I created a pull request, my tech lead did a code review of both the answer. And we agreed upon that this solution follows the best practices and structure-wise also it is correct. It will be easy to make changes if required in future. Tough I had to rename some variables `username`. ;-) – Tanzeel Mar 06 '20 at 10:06
  • @Tanzeel, Thanks for the update.. Glad to get a review on the solution from your team.. – Maniraj Murugan Mar 06 '20 at 11:20
  • Hi, can you please explain **filter.service.ts**, what it is doing. What is `username` there? – Tanzeel Mar 09 '20 at 05:42
  • @Tanzeel, Nowhere ```filter.service.ts``` is useful in that link and you can remove it.. I just created initially but later moved to ```filter-panel.service.ts``` and you need to only look at the ```filter-panel.service.ts``` .. – Maniraj Murugan Mar 09 '20 at 06:08
1

If both component don't have parent child relationship and if you want to pass the data between them then you can implement the RxJS subject for the same. I hope it helps you out

Message Service

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

@Injectable({ providedIn: 'root' })
export class MessageService {
    private subject = new Subject<any>();

    sendMessage(message: string) {
        this.subject.next({ text: message });
    }

    clearMessages() {
        this.subject.next();
    }

    getMessage(): Observable<any> {
        return this.subject.asObservable();
    }
}

filter-panel.component.ts

import { Component, OnInit } from '@angular/core';
import { messageService } from '../MesssageService.ts'
@Component({
    ...
})
export class FilterPanelComponent implements OnInit {

public activeFilters: string[];
public text: string="hello world";

constructor(private messageService: MessageService) {
    this.activeFilters = [
        'Apple',
        'Grapes',
        'Bana'
    ];
 }

ngOnInit() {}
     this.messageService.sendMessage('data from filterPanelComponent'); // here you can also pass the object 
}

filter-bar.component.ts

import { Component, OnInit, ViewChild } from '@angular/core';
import { messageService } from '../MesssageService.ts'

@Component({
    ...
})
export class FilterBarComponent implements OnInit {

    constructor(private messageService: MessageService) {

    }

    ngOnInit() {
     this.messageService.getMessage().subscribe(response => {
     // here we get the data from another component
      console.log(response);
     })
    }
}

Yash Rami
  • 2,276
  • 1
  • 10
  • 16
  • I implement this solution but there's something that is still not working. Can you please See this stackblitz i just created: https://stackblitz.com/edit/angular-ecginl – Tanzeel Mar 06 '20 at 06:49
  • @Tanzeel sure!! – Yash Rami Mar 06 '20 at 06:50
  • The error says: `Unexpected token. A constructor, method, accessor, or property was expected.` – Tanzeel Mar 06 '20 at 06:50
  • I made some more changes. But still the same error is there. :-( – Tanzeel Mar 06 '20 at 07:02
  • @Tanzeel https://stackblitz.com/edit/angular-8qab9i you can implement same in your project – Yash Rami Mar 06 '20 at 07:19
  • 1
    Now I've two people who helped me. :-) And both are working. Whom do I accept now. :-) – Tanzeel Mar 06 '20 at 07:21
  • 1
    Hi Yash, your answer is correct. But we feel that the other answer follows the best practice and preferred coding style. Thanks a lot for your help. Will again disturb you someday :-) – Tanzeel Mar 06 '20 at 10:02