Reputation: 49
I have PropertyComponent(Parent) and FeaturesComponent(Child), each one has its own service. On receiving the response from parent I send the selected features to the child and on receiving the child response I change the "isChecked= true" according to the selected features from parent.
The problem that sometimes the child response is received before the parent response so all features will be "isChecked= false".
I need to delay the child request till the parent response is received.
Property model:
export class Property {
id: string;
numberOrName: string;
selectedFeatures: string[];
}
Property service:
export class PropertService{
getPropert(id: number){
this.http.get(baseUrl + id).map((response: Response) => <Property[]>response.json().data);
}
Property component:
export class EditPropertyComponent implements OnInit{
@ViewChild('pf') propertyFeatures: PropertyFeaturesComponent;
editProperty: Property;
id: string;
constructor(private propertyService: PropertyService){}
ngOnInit() {
this.route.params
.map(params => params['id'])
.do(id => this.id = id)
.subscribe(id => {
this.getProperty(id);
});
}
getProperty() {
this.propertyService.getOne(this.id).subscribe(
prop => {
this.editProperty = prop;
this.selectedFeatures = prop.selectedFeatures;
this.propertyFeatures.selectedFeatures = this.selectedFeatures;
}
);
}
}
Feature service:
export class FeatureService {
constructor(private http: Http) { }
get() {
return this.http.get(this.baseURL)
.map((response: Response) => {console.log(response.json().data); return <Feature[]>response.json().data;});
}
}
property feature component (child):
export class PropertyFeaturesComponent implements OnInit {
@Input() selectedFeatures: string[];
features: Feature[];
constructor(private featureService: FeatureService) { }
ngOnInit() {
this.getFeatures();
}
getFeatures() {
this.featureService.get()
.subscribe((res) => {
this.features = res;
//If the parent response received before this subscribe then selectedFeatures will contain values otherwise the next line will be useless. this.selectedFeatures is an @Input() and I send its value from parent
this.features.filter(f => this.selectedFeatures.find(s => s == f.id)).forEach(f => f.isChecked = true);
});
}
}
I wish the problem is clear.
Upvotes: 1
Views: 181
Reputation: 13397
It sounds like you will need to initiate serial requests to ensure timing between parent and child (which I believe that you already know).
There are a few ways to accomplish this, but this is the method that I prefer for simplicity.
Overview (TLDR)
ParentComponent::ngOnInit()
fires making your first request. On success/failure ParentComponent
"alerts" the ChildComponent
through @Input() data: any; // Or whatever type
. ChildComponent::ngOnChanges()
then initiates the second request on change of its data property.
Code Sample
Using your code as a reference, I've tried to create this example, but it may require a little more refactoring that you'd like to perform.
property.component.ts:
import { Component, OnInit } from '@angular/core';
import { ActiveRoute } from '@angular/router';
import { PropertyService } from './property.service';
import { Property } from './property.model';
@Component({
selector: 'property-component',
templateUrl: './property.component.html',
styleUrls: ['./property.component.css']
})
export class PropertyComponent implements OnInit {
editProperty: Property;
id: string;
constructor(
private route: ActiveRoute,
private propertyService: PropertyService) { }
ngOnInit(): void {
this.route.params
.map(params => params['id'])
.do(id => this.id = id)
.subscribe(id => {
this.getProperty(id);
});
}
getProperty(): void {
this.propertyService.getOne(this.id).subscribe(
prop => {
// Looks like prop already had features, so I removed it for
// brevity, but you can add it back if needed
this.editProperty = prop;
}
);
}
property.component.html:
<div>
... <!-- Other markup -->
<feature-component
*ngIf="editProperty"
[propertyData]="editProperty">
</feature-component>
</div>
feature.component.ts:
import { Component, OnChanges, Input } from '@angular/core';
import { FeatureService } from './feature.service';
import { Property } from './property.model';
@Component({
selector: 'feature-component',
templateUrl: './feature.component.html',
styleUrls: ['./feature.component.css']
})
export class FeatureComponent implements OnChanges {
@Input()
private propertyData: Property; // Looks like editProperty already has features, so I removed it for brevity
constructor(private featureService: FeatureService) { }
ngOnChanges(): void {
// Fires when propertyData changes
if (this.propertyData) {
// Whatever you need to do with this.propertyData.selectedFeatures
this.featureService.get(...).subscribe((...) => {
// Do work. Removed for brevity
// If you need to alert the parent of a change in features for some reason, you
// can use an EventEmitter, but be careful of an infinite loop.
});
}
}
}
Note: Untested code for illustration.
I hope this helps!
Upvotes: 1