Dheeraj Agrawal
Dheeraj Agrawal

Reputation: 2357

Angular 2 search using http

I have a couple of components one is to get data and render it to dom & another is to make search API call and render that searched data is first components view. I have attached the image to get more clear view:

enter image description here

So the problem I am facing here is for the searching I need to pass the searched data to parent component so that it can render it, I am using input / output for this, below is my code:

// SpreadSheet Component - Component 1
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { Http, HTTP_PROVIDERS, Headers, Response } from "@angular/http";
import { Observable } from 'rxjs/Rx';
import { ContactService } from '../../services/contactService';

@Component({
  selector: 'spreadsheet',
  pipes: [],
  providers: [ContactService],
  directives: [],
  styleUrls: ['./spreadsheet.css'],
  templateUrl: './spreadsheet.html',
  inputs: ['contactlist']
})
export class Spreadsheet {
  public contactlist = [];
  public sortOrder = 'asc';
  public editDisabled = true;
  sortCol = 'name_given';
  toggle = false;
  defaultPage = 0;
  defaultPageSize = 20;
  pageNumber = this.defaultPage
  pageSize = this.defaultPageSize;

  constructor(private contactService: ContactService) {}

  ngOnInit() {
    this.getContacts();
  }

  getContacts(sorting = false) {
    this.contactService.getName(this.pageNumber, this.pageSize, this.sortCol, this.sortOrder)
      .subscribe(
        data => { 
          if(!this.contactlist.length || sorting) {
            this.contactlist = data.results;  
          } else {
            for (let contact of data.results) {
              this.contactlist.push(contact);
            }
          }
        },
        err => console.error(err),
        () => console.log('Contact list fetched...')
      );
  }
}

// Search Component - Component 2
import { Component, Input } from '@angular/core';
import { Http, HTTP_PROVIDERS, Headers, Response } from "@angular/http";
import { Observable } from 'rxjs/Rx';
import { ContactService } from '../../services/contactService';
import { Spreadsheet } from '../spreadsheet/spreadsheet.component';

@Component({
  selector: 'searchForm',
  pipes: [],
  providers: [ContactService],
  directives: [Spreadsheet],
  styleUrls: ['./search.css'],
  templateUrl: './search.html'
})
export class Search {
  searchedList = [];
  constructor(private contactService: ContactService) {}

  searchContact(searchKey) {
    this.contactService.searchContact(searchKey)
      .subscribe(
        data => { 
          this.searchedList = data.results;
        },
        err => console.error(err),
        () => console.log('Search result fetched...')
      );
  }
}

Now in search.html to pass search result data to parent component I am doing this:

<form class="form-inline pull-xs-right">
    <input class="form-control" type="text" [(ngModel)]="searchKey" placeholder="Search">
    <button class="btn btn-success-outline" type="submit" (click)="searchContact(searchKey)">Search</button>
</form>
<spreadsheet [contactlist]="searchedList"></spreadsheet>

Now here the problem is my spreadsheet view rendered twice since I have in search component and one is by using routing. So is there any way to prevent rendering from search and it should render that first components view and update data there.

Or is there any other way to achieve this changing data from one component to another

Upvotes: 1

Views: 3697

Answers (1)

inoabrian
inoabrian

Reputation: 3800

So what you want to do is have a rxjs subject in your service.

private _contactObject = new Subject < any > ();
contactDataAnnounced$ = this._contactObject;

And when you call the ContactService you will utilize it to sync data between both components.

// SpreadSheet Component - Component 1
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { Http, HTTP_PROVIDERS, Headers, Response } from "@angular/http";
import { Observable } from 'rxjs/Rx';
import { ContactService } from '../../services/contactService';

@Component({
  selector: 'spreadsheet',
  pipes: [],
  providers: [ContactService],
  directives: [],
  styleUrls: ['./spreadsheet.css'],
  templateUrl: './spreadsheet.html',
  inputs: ['contactlist']
})
export class Spreadsheet {
  public contactlist = [];
  public sortOrder = 'asc';
  public editDisabled = true;
  sortCol = 'name_given';
  toggle = false;
  defaultPage = 0;
  defaultPageSize = 20;
  pageNumber = this.defaultPage
  pageSize = this.defaultPageSize;

  constructor(private contactService: ContactService) {
     // You can subscribe here to the subject in your service to know when new data has been pushed.
     let self = this;
     this.contactService.contactDataAnnounced$.subscribe(contact =>{
        self.contactlist = contact;
     });
  }

  ngOnInit() {
    this.getContacts();
  }

  getContacts(sorting = false) {
    this.contactService.getName(this.pageNumber, this.pageSize, this.sortCol, this.sortOrder)
      .subscribe(
        data => { 
          if(!this.contactlist.length || sorting) {
            this.contactlist = data.results;  
          } else {
            for (let contact of data.results) {
              this.contactlist.push(contact);
            }
          }
          // Will send this contact list to the search component also because it is subscribed to the _contactObject subject.
          this._contactObjectnext(this.contactList);
        },
        err => console.error(err),
        () => console.log('Contact list fetched...')
      );
  }
}

// Search Component - Component 2
import { Component, Input } from '@angular/core';
import { Http, HTTP_PROVIDERS, Headers, Response } from "@angular/http";
import { Observable } from 'rxjs/Rx';
import { ContactService } from '../../services/contactService';
import { Spreadsheet } from '../spreadsheet/spreadsheet.component';

@Component({
  selector: 'searchForm',
  pipes: [],
  providers: [ContactService],
  directives: [Spreadsheet],
  styleUrls: ['./search.css'],
  templateUrl: './search.html'
})
export class Search {
  searchedList = [];
  constructor(private contactService: ContactService) {
      let self = this;
      this.contactService.contactDataAnnounced$.subscribe(search=>{
        self.searchedList = search;
      });
  }

  searchContact(searchKey) {
    this.contactService.searchContact(searchKey)
      .subscribe(
        data => { 
          this.searchedList = data.results;
          this._contactObject.next(this.searchList)
        },
        err => console.error(err),
        () => console.log('Search result fetched...')
      );
  }
}

Upvotes: 1

Related Questions