I am trying to generate a string (which will be formed by concatenating the apiUrl queryParams) with the data I receive from a form (Reactive Form). I have already found a solution, but I think it is the ugliest and less professional thing ever created. I provide some code next.
component.ts
stringFinal : string = ''
this.myForm= this.fb.group({
input1: new FormControl(),
input2: new FormControl(),
input3: new FormControl(),
});
generateUrl() {
let qry1 = this.myForm.get("input1")?.value
let qry2 = this.myForm.get("input2")?.value
let qry3 = this.myForm.get("input3")?.value
if(qry1 != null) {
this.stringFinal = `qry1=${qry1}&`
}
if(qry2 != null) {
this.stringFinal = `qry2=${qry2}&`
}
if(qry3 != null) {
this.stringFinal = `qry3=${qry3}&`
}
console.log(this.stringFinal);
}
This works fine, but it is not really scalable, and if I wanted, in the future, add 50 more inputs to the form, I would have to add manually 50 more conditions.
Also, in some cases, instead of receiving only strings from the form, I will also receive objects, and in that case, I will not be able to retrieve the data. I provide an example.
input4: (2) [{...},{...}]
My questions are 2:
- How to improve the URL generation without doing what I showed.
- How to retrieve an specific field (for example, the name), when I receive an array instead of a string.
CodePudding user response:
You can improve on your url generation by iterating over the controls
property of your FormGroup
:
stringFinal: string = "";
generateUrl() {
for(const control in this.myForm.controls){
const val = this.myForm.controls[control].value;
if(val !== null){
this.stringFinal = `${control}=${val}&`;
}
}
}
If you not only have strings but also objects as values in your form, you have to verify the type of the control value first, for example with a typeguard:
interface Person
name: string;
id: number;
}
function isPerson(a_obj: any): a_obj is Person {
return `name` in a_obj && 'id' in a_obj;
}
And to put it alltogether:
interface Person {
name: string;
id: number;
}
stringFinal: string = "";
generateUrl() {
for(const control in this.myForm.controls){
const val = this.myForm.controls[control].value;
if(val === null) continue;
if(isPerson(val)){
this.stringFinal = `${control}=${val.name}&`;
} else {
this.stringFinal = `${control}=${val}&`;
}
}
}
function isPerson(a_obj: any): a_obj is Person {
return `name` in a_obj && 'id' in a_obj;
}