0

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:

  1. How to improve the URL generation without doing what I showed.
  2. How to retrieve an specific field (for example, the name), when I receive an array instead of a string.
3
  • FormGroup has a property controls, which is an object that holds all the controls with their names as keys. for(const control in this.myForm.controls){ console.log(myForm.controls[control]) }. This should make iterating a little easier. Commented Sep 22, 2022 at 7:32
  • How to retrieve an specific field (for example, the name), when I receive an array instead of a string. What exactly do you mean with that? Commented Sep 22, 2022 at 7:34
  • Look where I put the input4, that is an Array of two objects, for example Person. That object contains, for example, age, name, etc etc. I want for every Person object, retrieve the name. Commented Sep 22, 2022 at 7:40

1 Answer 1

0

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;
}
Sign up to request clarification or add additional context in comments.

2 Comments

This answer is very close to what I need, but firts I need to check if the input is filled (because they are not requiered), and if the input is null, not adding it, and if the input is not null, append the name of the query parameter, followed by the symbol =, followed by the data, and finally, followed by the symbol &
@AhmedSHA256 You can use a simple null check and template srtings to implement your requirements. I've edited the answer, but you may have to adjust the template strings to fit your needs.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.