1

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

7
  • I don't quite understand the issue here. Commented Jul 12, 2016 at 3:58
  • That contact table will be visible twice, first from the search component & other from the self component (spreadsheet) & the searching result will be effected only on search component table, so here only one table should be visible (spreadsheet component table not search) Commented Jul 12, 2016 at 4:03
  • Or is there any other way to update one components variable from other component? without using input output Commented Jul 12, 2016 at 4:15
  • So what you want to do is find a way to tunnel data to the original table so you won't have two sets of data. Commented Jul 12, 2016 at 4:15
  • right & I guess in this condition input output will not be helpful right? Commented Jul 12, 2016 at 4:16

1 Answer 1

1

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...')
      );
  }
}
Sign up to request clarification or add additional context in comments.

Comments

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.