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.

8
  • 1
    Does this answer your question? How to share data between components using a service properly? Commented Mar 6, 2020 at 6:26
  • check this out fireship.io/lessons/… the last section "Unrelated Components: Sharing Data with a Service" Commented Mar 6, 2020 at 6:29
  • 1
    @Tanzeel check this link. Any via a shared service medium.com/@onejohi/… Commented Mar 6, 2020 at 6:31
  • 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. Commented Mar 6, 2020 at 6:45
  • 1
    @Tanzeel, Can you look at my below solution, here I have passed this.activeFilters array from filter panel to filter bar component.. Commented Mar 6, 2020 at 7:15

2 Answers 2

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..

Sign up to request clarification or add additional context in comments.

13 Comments

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, 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..
@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..
I accepted the solution because I wanted to see how service is created and used. From there I can handle things my way. :-)
@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..
|
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);
     })
    }
}

7 Comments

I implement this solution but there's something that is still not working. Can you please See this stackblitz i just created: stackblitz.com/edit/angular-ecginl
@Tanzeel sure!!
The error says: Unexpected token. A constructor, method, accessor, or property was expected.
Now I've two people who helped me. :-) And both are working. Whom do I accept now. :-)
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 :-)
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.