Issue
i have a component called DipComponent.ts and in this component i have a function named submit, this function pass 3 datas to a function in another page called DipService.ts(ine array, one number and another array). the last array(an array of objects) is full of data in the page DipComponent.ts but when i try to read it in the DipService.ts it looks empty. here is my code of DipComponent.ts:
import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { competenza } from '../interfaces/competenza';
import { dipendente } from '../interfaces/dipendente';
import { AssenzeService } from '../services/assenzeservice';
import { CompetenzeService } from '../services/competenzeservice';
import { DipendentiService } from '../services/dipendenteservice';
@Component({
selector: 'app-modificadip',
templateUrl: './modificadip.component.html',
styleUrls: ['./modificadip.component.css']
})
export class ModificadipComponent implements OnInit {
[x: string]: any;
public dipendentemodificato: any[] = [];
public dip: dipendente[] = [];
public competenze: competenza[]=[];
public competenzeDip: competenza[]=[];
public competenzeposs = [];
public optionsMap=<any>[];
public optionsChecked = <any>[];
public options=<any>[];
public stringtemp: string=''
public Comps=<any[]>([])
public idcomp!: number[];
constructor (private route : ActivatedRoute, public DS:DipendentiService, public
CS:CompetenzeService, public AS:AssenzeService) {
var id=this.route.snapshot.params.id
this.DS.getdipendentebyid(id).toPromise().then(data =>{console.log(data);
for(let i in data){
this.dip.push(data[i]);
}
});
this.CS.getcompetenze().toPromise().then(data =>{console.log(data);
for(let i in data){
this.competenze.push(data[i]);
}
});
this.CS.getcompetenzebyiddipendente(id).toPromise().then(data =>{console.log(data);
for(let i in data){
this.competenzeDip.push(data[i]);
}
});
}
ngOnInit(): void {
this.initOptionsMap();
}
submit(login: any){
console.log("submit dipendente", login)
for(let i in login){
this.dipendentemodificato.push(login[i]);
}
console.log("modifiche del dipendente: "+this.dipendentemodificato)
//----------------
for(var x in this.optionsMap) {
if(this.optionsMap[x]) {
this.optionsChecked.push(x);
}
}
for (var k = 0; k<this.optionsChecked.length; k++) {
console.log("id competenza "+this.optionsChecked[k])
this.CS.getcompetenzabyid(this.optionsChecked[k]).toPromise().then(data =>{console.log("datas: "+JSON.stringify(data));
this.Comps.push(data);
});
}
console.log(this.Comps)
//----------------
this.DS.postmoddipendenti(this.dipendentemodificato, this.route.snapshot.params.id, this.Comps)
}
initOptionsMap() {
for (var x = 0; x<this.competenze.length; x++) {
this.optionsMap[x] = true;
}
}
updateCheckedOptions(option:number, event:any) {
this.optionsMap[option] = event.target.checked;
console.log("dopo aggiornamento "+this.optionsMap[option])
}
}
here is my code of the interested function of DipService.ts:
postmoddipendenti(raw: any,id:number,comp=<any[]>([])){
console.log("::::::"+ comp)
var dip = '{' +'"id"'+':'+id+','+'"nome"'+':'+'"'+raw[0]+'"'+','+'"cognome"'+':'+'"'+raw[1]+'"'+','+'"data_nascita"'+':'+'"'+raw[2]+'"'+','+'"mail"'+':'+'"'+raw[3]+'"'+','+'"telefono"'+':'+raw[4]+','+'"setCompetenze"'+':'+'[]' +'}'
console.log("non json ->"+ dip)
//const obj = JSON.parse(dip);
//console.log("obj ->"+ obj)
// this.http.post<any>('http://localhost:8080/postdipendenti', obj).subscribe(
// (val) => {console.log("POST call successful value returned in body", val);
// })
}
thank you and sorry for my bad english.
Solution
I think your variable this.Comps is empty because you fill it in an asynchronous way :
this.CS.getcompetenzabyid(this.optionsChecked[k]).toPromise().then(data =>{console.log("datas: "+JSON.stringify(data));
this.Comps.push(data);
});
So when you do
this.DS.postmoddipendenti(this.dipendentemodificato, this.route.snapshot.params.id, this.Comps)
Maybe the array is not filled yet.
What does your console.log(this.Comps)
display ? If it's an empty array I think it's because of that.
So in that case you should wait for all the events to finish.
In your case you use .toPromise()
so you could do a Promise.all instead of a forEach.
But note that, in most cases, it's recommended to avoid Promises in Angular and to keep using Observables. You can check the Angular documentation and RxJs library if you want to know more about that.
Anyway for now I don't see over explanations besides asynchronism.
EDIT:
An example to show you how await Promises and Promise.all() work. But you can (and should) find much more detailed tutorials about that on the web.
So when you do
this.CS.getcompetenzabyid(this.optionsChecked[k]).toPromise()
you will get a promise. It's not a value you can directly use yet. It will resolve and give you the final value but you don't know exactly when. For example, it's what happens when you run a SQL request from your code. You don't know how long the request will take.
And Javascript is a "non-blocking" language. This means it will not wait for the DB to answer, it does something else to not waste time. And in our case something else means "Continue to execute the code".
The Promise object we get before allow javascript to take care of the result when it finally arrive (and when that happens you can be really far in your code already).
So to take care of this Promise you have 2 ways :
- Or you give a callback to the
then
keyword. - Or you use the keyword
await
to "block" the code
With the then
approach (what you used in your code) you can't force javascript to not execute the code written after your then.
But with the await
you can. You would write something like that :
const data = await this.CS.getcompetenzabyid(this.optionsChecked[k]).toPromise()
Like that you would get the result of the Promise (when it's resolved) in the variable "data". And with the await
keyword javascript will wait the result without executing anymore code.
So to sum up you can just write:
const data = await this.CS.getcompetenzabyid(this.optionsChecked[k]).toPromise(); this.Comps.push(data);
And you will be sure that this.Comps will be up to date. If you have only one request to do.
But in your case you have few promises because you do few requests in your forEach. So you need to wait for all of them. For that we can use the function Promise.all() that will wait all the Promises you give him.
So in your case :
const datas = [];
for (var k = 0; k<this.optionsChecked.length; k++) {
//create array of Promises
datas.push(this.CS.getcompetenzabyid(this.optionsChecked[k]).toPromise());
}
// Wait for all the promises to resolve and get all the datas
const resolvedDatas = await Promise.all(datas);
this.Comps = resolvedDatas;
Like this you should have all the values from your request in the Comps variable. And you sure that the call to the service will not be done before you get all the datas.
I hope it's clear. I tried to make it short so don't hesitate to look for more informations online.
And I hope it will solve your issue. But even if it doesn't it can avoid bugs in the future.
Answered By - Valentin Roche
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.