0

So, I am creating a basic Airbnb search. I have 3 components: SearchComponent, which includes the search form; ListingComponent, which lists the Airbnb rentals; and MapComponent, which shows a marker where each rental is located, on a google map. The SearchComponent is a parent component to both the ListingComponent and MapComponent and I am using the Router module to navigate between the two child components. In order for the two child components to display the rentals in the list or map, they will need the form's input value inside of the SearchComponent. How do I pass this value to both of the child components?

search.component.html

I want this locationSearch input value to be passed through the <router-outlet></router-outlet> to both of my child components.

<form class="mui-form">
    <div class="mui-textfield mui-textfield--float-label">
        <input type="text" name="locationSearch" [(ngModel)]="locationSearch" (keyup)="searchLocation()">
        <label>Location</label>
    </div>
</form>

<router-outlet></router-outlet>

search.component.ts

import { Component, OnInit } from '@angular/core';
import { SearchService } from "app/search.service";

@Component({
  selector: 'app-search',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.scss']
})
export class SearchComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

UPDATE - Still doesn't seem to be working

For some reason my location property in my list.component.ts isn't updating when I change the search.

Routes

const appRoutes: Routes = [
    { path: '', component: SearchComponent, children: [
        { path: '', redirectTo: 'listing', pathMatch: 'full' },
        { path: 'listing', component: ListingComponent },
        { path: 'map', component: MapComponent }
    ]},
    { path: 'detail/:id', component: ListingDetailComponent },
];

search.service.ts

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/Rx';

@Injectable()
export class SearchService {
    private _inputValue = new BehaviorSubject('Starting Value');
    inputValue$ = this._inputValue.asObservable();

    updateSearch(search: string) {
        this._inputValue.next(search);
    }
}

search.component.ts

The location value is updating in this component, but not in list.component.ts

import { Component, OnInit, OnDestroy } from '@angular/core';
import { SearchService } from "app/search.service";
import { Subscription }   from 'rxjs/Subscription';

@Component({
    selector: 'app-search',
    templateUrl: './search.component.html',
    styleUrls: ['./search.component.scss'],
    providers: [ SearchService ]
})
export class SearchComponent implements OnInit {
    locationSearch: string;
    location: string = 'None';

    constructor(private searchService: SearchService) {
        this.searchService.inputValue$.subscribe(res => this.location = res); // This location value is updating
    }

    ngOnInit() {}

    updateInput() {
        this.searchService.updateSearch(this.locationSearch);
    }
}

list.component.ts

import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { AirbnbService } from "app/airbnb.service";
import { SearchService } from "app/search.service";
import { Subscription }   from 'rxjs/Subscription';

@Component({
  selector: 'app-listing',
  templateUrl: './listing.component.html',
  styleUrls: ['./listing.component.scss'],
  providers: [ SearchService ]
})
export class ListingComponent implements OnInit {
    listings;
    location: string = 'None';

    constructor(private airbnb: AirbnbService, private searchService: SearchService) {
        this.searchService.inputValue$.subscribe(res => this.location = res);

        // Output rentals
        this.airbnb.getByLocation().subscribe(res => {
            console.log(res.search_results);
            this.listings = res.search_results; // this listings property isn't updating for some reason.
        });
    }

    ngOnInit() {}
}

Image of what is happening

1 Answers1

0

I have just done something very similar (successfully) and I'm pretty sure that you are simply providing the SearchService too many times. Your code is creating two instance of the SearchService and so they hold different values.

You need a singleton so only write providers: [ SearchService ] once. This will be at the highest parent level of all your components (which I think is search.component.ts).

Try modifying your child:

import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { AirbnbService } from "app/airbnb.service";
import { SearchService } from "app/search.service";
import { Subscription }   from 'rxjs/Subscription';

@Component({
  selector: 'app-listing',
  templateUrl: './listing.component.html',
  styleUrls: ['./listing.component.scss']//,
  //providers: [ SearchService ] // REMOVE THIS LINE

})
export class ListingComponent implements OnInit {
    listings;
    location: string = 'None';

    constructor(private airbnb: AirbnbService, private searchService: SearchService) {
        this.searchService.inputValue$.subscribe(res => this.location = res);

        // Output rentals
        this.airbnb.getByLocation().subscribe(res => {
            console.log(res.search_results);
            this.listings = res.search_results; // this listings property isn't updating for some reason.
        });
    }

    ngOnInit() {}
}