why isn’t my function able to collect user input from a ngForm?

I’m working on the class of my angular component. I’m simply trying to collect the user input from a form and trying to make an array of those words.

the parameter “data” to my submit function is the ‘value’ attribute to the ngForm. So in my case if the user input is “hello world” then logging data to the console will show this {word_1: "hello", word_2: "world" } and typeof keyword tells me that it’s of type object.

the function seems to crash my app on the first for loop and I can’t figure out why that causes an issue. Any help?

important notes:

  • The reason why I’m doing it this way is because I will have an unknown amount of inputs. so it’s not known beforehand how many keys I will have (word_1 . . . word_N).
  • the variable this.inputBoxes doesn’t hold a value until after the onClickSubmit function is called so that is why I’m trying to figure out how to “declare a global array but instantiate it later” in typescript

this is the function im using to collect the “hello” and “world” but it keeps crashing my webpage and I can’t figure out why.

component.ts

  public inputBoxes: any; 
  private keys: Array<string>;

onClickSubmit(data) {

    let num = parseInt(this.inputBoxes); 
    this.keys = new Array(num);

    for (let idx = 0; idx < num; idx++){
      this.keys[idx] = Object.keys(data)[idx];
    }


    for (let i = 0; i < num; i++){
      console.log(data.keys[i]);
    }

 }

This is my html in case it’s needed but I doubt anything from here is causing the problem

component.html

<p>How many words will you be using?</p>
<select (change)="updateInputBoxes($event)">
    <option value="">Select Count</option>
    <option *ngFor="let num of dropdown_numbers" value={{num}}> {{num}} </option>
</select>

<div *ngIf="inputBoxes">
    <form #allWords = "ngForm" (ngSubmit)= "onClickSubmit(allWords.value)" >
        <label>Enter the Words for your Crossword</label>
        <div *ngFor="let box of createInputBoxes">
            <input required ngModel name="word_{{box}}" #word="ngModel" class="form-control">
            <div class="alert alert-danger" *ngIf=" word.touched && !word.valid"> Missing word, please insert a word </div> 
        </div>
        <button type="submit" value="submit">Submit</button>
    </form>
</div>

Answer

you can use [(ngModel)] in a more confortable way

inputs:any[]=[]
inputBoxes: any; 

The .html using [(ngModel)]

    <!--see the select with ngModel-->
    <select [(ngModel)]="inputBoxes" (ngModelChange)="inputs=inputs.slice(0,$event)">
        <option value="">Select Count</option>
        <!--You can use a variable or directly use an array-->
        <option *ngFor="let num of [1,2,3,4,5,6,7,8,9,10]"
            [value]="num"> {{num}} </option>
    </select>
    <div *ngIf="inputBoxes">
        <form #allWords = "ngForm" (ngSubmit)= "onClickSubmit(allWords.value)" >
            <label>Enter the Words for your Crossword</label>
            <!--you can use pipe slice, see that it's the same array than the select
                use "let i=index" to get the index from 0 to ...
             -->
            <div *ngFor="let box of [1,2,3,4,5,6,7,8,9,10] |slice:0:inputBoxes;let i=index">
               <!--the ngModel is inputs[i], this makes your array inputs create the array
                   automatically
               -->
                  
                <input required [(ngModel)]="inputs[i]" name="word_{{box}}" #word="ngModel" class="form-control">
                <div class="alert alert-danger" *ngIf=" word.touched && !word.valid"> Missing word, please insert a word </div> 
            </div>
            <button type="submit" value="submit">Submit</button>
        </form>
    </div>

in your function onClickSubmit your can

onClickSubmit(value:any)
{
    console.log(value) //<--get the value of form
    console.log(this.inputs)  //<--get the array this.inputs
}

See stackblitz