0

I'm new to Angular. This question is very much similar to mine but doesn't answers my question. In my case, the two components are stand-alone, that means they ain't parent-child to each other. They're separate and at same directory level. That's why my problem is different from the rest. I tried using:

  1. @ViewChild();
  2. @Output() ....EventEmitter()

But I'm still getting an error in navbar.component.ts:

ERROR TypeError: "this.articles is undefined"

My first component is NavBar and my second component is Articles

So the scenarioa is, pressed() method of NavBar have to call callSearch(arg) method of Articles.

Here is my navbar.component.ts

import { ..., ViewChild } from '@angular/core';
import { ArticlesComponent } from '../articles/articles.component';

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

  text='something';

  @ViewChild(ArticlesComponent, {static: false}) articles: ArticlesComponent;

  constructor() { }

  /*  This method is called on click event from HTML page*/
  pressed(text: string) {
    this.articles.callSearch(text);
  }

  ngOnInit() {
  }
}

navbar.component.html

<li class="nav-item">
  <button class="btn" (click)="pressed(text)">Search</button>
</li>

And here is the component whose method I want to call from NavBar.

articles.component.ts

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

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

  articles = [];
  filteredArticles=[];

  constructor(...) { }

  ngOnInit() {
    ...
  }

  /*  this is called from navbar typescript and it will call SearchFunction below*/
  callSearch(text: string) {
    this.SearchFunction(text);
  }

  SearchFunction(text: string) {
    this.filteredArticles=(this.articles.filter(e => {
      /* some logic*/
    }));
  }
}

articles.component.html

<div *ngFor="let article of filteredArticles; let i = index;">
  <div class="card text-center">
    <div class="card-body">
      <!-- card design related html -->
    </div>
  </div>
</div>

Please correct me.

PS: Here is the stackblitz.

Tanzeel
  • 4,174
  • 13
  • 57
  • 110
  • Can you include the html of the components? – igg Jan 15 '20 at 12:21
  • Does this [answer](https://stackoverflow.com/questions/54784980/angular-7-communication-through-service-subscribe-method-called-twice) your question – Mustafa Kunwa Jan 15 '20 at 12:21
  • _"the two components are stand-alone, that means they ain't parent-child to each other"_ - then `@ViewChild` can't possibly work. You might want to communicate through their common parent component (if they belong to common parent component), or a service. – mbojko Jan 15 '20 at 12:22
  • Ok. I'll include HTML here. In fact I'm trying to create stackblitz. that will be more easy for everyone i think. – Tanzeel Jan 15 '20 at 12:22
  • Please include the `html` in your question body and a stackblitz would be great as well. – igg Jan 15 '20 at 12:23
  • @mbojko. that's the problem. there's no common service between ten. One isNavbar item and the other is Atricle that reads all articles from mongodb. – Tanzeel Jan 15 '20 at 12:23
  • 1
    here is [stackblitz](https://stackblitz.com/edit/angular-tbhdwe) – Mustafa Kunwa Jan 15 '20 at 12:33
  • @MustafaKunwa. I'm creating a stackblitz. I've seen your solution also. :-) Will get back to you. give me 5 min – Tanzeel Jan 15 '20 at 12:35
  • Here is the stackblitz: https://stackblitz.com/edit/angular-fgge3w – Tanzeel Jan 15 '20 at 12:37
  • @IraklisGkougkousis https://stackblitz.com/edit/angular-fgge3w – Tanzeel Jan 15 '20 at 12:38

1 Answers1

1

To communicate two components that are not related to each other, you can use a service.

    @Injectable({
    providedIn: 'root',
})
export class YourService {

    private yourVariable: Subject<any> = new Subject<any>();


    public listenYourVariable() {
        return this.yourVariable.asObservable();

    }


    private yourVariableObserver(value : type) {
        this.yourVariable.next(value);
    }

You import in yours components where you want use it this service.

import{ YourService } from ...

In component you want write the data call:

this.yourService.yourVariableObserver(yourData);

while where you want read the data:

 this.yourService.listenYourVariable().subscribe(
    variable => {
      this.data = variable;
      this.callyourFunction();
    }

)

Obviously you can simple call the function without pass any value.

FedG
  • 1,218
  • 1
  • 5
  • 14
  • Can you see this stackblitz: https://stackblitz.com/edit/angular-fgge3w – Tanzeel Jan 15 '20 at 12:38
  • You create the service how i did and then in navBar component call this.yourService.yourVariableObserver(arg); and in articles this.yourService.listenYourVariable().subscribe( variable => { const arg = variable; this.callSearch(arg) } ) – FedG Jan 15 '20 at 12:50
  • Sure I'll give it i shot. I appreciate your help. :-) – Tanzeel Jan 15 '20 at 12:51