Reputation: 2357
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:
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
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