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 :-)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.