Timing plays a crucial role in this issue. With the service call being asynchronous, the data does not arrive instantly when the subscribe function is triggered. Instead, the callback function specified as an argument to the subscribe method is executed upon receiving the response.
This explains why the console.log inside the Subscribe function functions properly.
Refer to the diagram below for a rough outline of the execution order:
https://i.stack.imgur.com/ULHXc.png
Your code will retain the value once it's fetched successfully.
To verify the existence of the value outside the subscribe function, you can simply check for its presence like so:
if (this.sessionTrackers) { console.log(...) }
If you're binding to the data, consider using *ngIf or the safe navigation operator (?) accordingly.
In case you're working with reactive forms, ensure you separate setting up the form model using FormBuilder from setting default values.
A sample of reactive forms can be found here: https://github.com/DeborahK/Angular2-ReactiveForms (look into the APM folder).
ngOnInit
ngOnInit(): void {
this.productForm = this.fb.group({
productName: ['', [Validators.required,
Validators.minLength(3),
Validators.maxLength(50)]],
productCode: ['', Validators.required],
starRating: ['', NumberValidators.range(1, 5)],
tags: this.fb.array([]),
description: ''
});
// Read the product Id from the route parameter
this.sub = this.route.params.subscribe(
params => {
let id = +params['id'];
this.getProduct(id);
}
);
}
This snippet establishes the reactive form and monitors changes in the route parameters. Any time the route parameter changes, getProduct(id) gets invoked.
getProduct
getProduct(id: number): void {
this.productService.getProduct(id)
.subscribe(
(product: IProduct) => this.onProductRetrieved(product),
(error: any) => this.errorMessage = <any>error
);
}
This section fetches data, similar to your implementation. Note that within the subscribe callback, I'm triggering another method named onProductRetrieved
.
onProductRetrieved
onProductRetrieved(product: IProduct): void {
if (this.productForm) {
this.productForm.reset();
}
this.product = product;
// Populate form data
this.productForm.patchValue({
productName: this.product.productName,
productCode: this.product.productCode,
starRating: this.product.starRating,
description: this.product.description
});
this.productForm.setControl('tags', this.fb.array(this.product.tags || []));
}
This is where I assign default values to the reactive form after ensuring the availability of the data. You can utilize either setValue or patchValue for this purpose.