2

I have two components HomePageComponent and StudentResultsComponent. I have an input in HomePageComponent that when I type, I want the value to be in my StudentResultsComponent input.

I thought of creating a separate component for the input and calling them in both components, but the value is not being updated in my StudentsResultsComponent when I start typing in HomePageComponent. Heres my code:

Career-Search-Component.html

<input
  #input
  type        ="text"
  id          ="searchInput"
  class       ="input-student-search validate filter-input"
  placeholder ="Search by a career (Software Engineer,Web Developer,Geologist, Geogropher etc.)"
  [(ngModel)] ="query"
>

Career-Search.component.ts

import {Component,OnInit,Input,EventEmitter} from '@angular/core';
@Component({
  selector: 'career-search',
  templateUrl: 'career-search.component.html'
})
export class CareerSearchComponent implements OnInit {
  @Input() public query: string;
  constructor() {}

  ngOnInit() {}

}

HomePageComponent.component.html

<career-search></career-search>
<button class="submit" [routerLink]="['/students']">Search</button>

Students-result.component.html

<career-search></career-search>

The reason why i need to pass the data from the homepage component is because I can then use the data to query it and show results based on the value being passed from the other component.

Please help.

Thanks

DingDong
  • 367
  • 3
  • 12
  • 22
  • What is this career-search component then? And you are not showing any of your templates.. where you *type in your home component* and also not template in your students result component where you expect to get the input? And what is the relationship between these two components? same level components, or parent child or what? :) – AT82 Mar 15 '17 at 16:48
  • Sorry I misunderstood you. So basically what I want is to get the value of the input typed in `HomePageComponent` and pass it to my input inside another component called `StudentResultsComponent` using **ngModel** @AJT_82 – DingDong Mar 15 '17 at 16:52
  • Ooookay... but where is the code for that *input typed in HomePageComponent* and how does the template (and ts code) look like? And what is the relationship between these components? This is also important information. If they are parent and child, you can use `Input()` if they are not parent and child, you need to use a shared service :) – AT82 Mar 15 '17 at 16:55
  • This is a good page to read how components can communicate with each other https://angular.io/docs/ts/latest/cookbook/component-communication.html – AT82 Mar 15 '17 at 16:59
  • Oh sorry about that. There is nothing important to show in the ts of HomePage. The relationship between them is just two different components. They are not children or what not. @AJT_82 – DingDong Mar 15 '17 at 17:01
  • sure ok, ill read that @AJT_82 – DingDong Mar 15 '17 at 17:01
  • Okay if they are not parent and child, then you need to use service to communicate between the components :) – AT82 Mar 15 '17 at 17:03

1 Answers1

4

If your two components don't have any other connection the only way I know of is to use a service. The link provided by AJT_82 has an example for it and here is the smallest example I can think of:

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

@Injectable()
export class InputService {

  public inputEvents: EventEmitter<string> = new EventEmitter();

  public inputChanged(val: string) {
    this.inputEvents.emit(val);
  }
}

@Component({
  selector: 'observer',
  template: `
    <p>Input value: {{ myValue }}</p>
`
})
export class ObserverComponent implements OnDestroy {

  private myValue: string;
  private subscription: Subscription;

  constructor(private service: InputService) {
    this.subscription = this.service.inputEvents.subscribe((newValue) => {
      this.myValue = newValue;
    })
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }
}

@Component({
  selector: 'observable',
  template: `
    <input [(ngModel)]="inputValue" />
`
})
export class ObservableComponent {

  private _inputValue: string;

  constructor(private service: InputService) {}

  public get inputValue(): string {
    return this._inputValue;
  }

  public set inputValue(val: string) {
    this._inputValue = val;
    this.service.inputChanged(val);
  }
}

@Component({
  selector: 'app-root',
  template: `

    <observable></observable>
    <observer></observer>

`
})
export class AppComponent {
}

Explanation:

The Observable Component stores the input-Value via two-way data binding. Within the setter we not only store the value, but also tell the service the value has changed. The service will then emit an inputChanged event, which the Observer subscribes to. It can then use the value however it likes.

andreas
  • 955
  • 7
  • 15