Le Svr
Le Svr

Reputation: 35

Html getting input in input field using Angular material

I'm working on an Angular project using Angular Material component library.

I'm making a form which has multiple fields and everything works, except that it just looks a little funny:

enter image description here

What's supposed to happen here is that a user chooses a number of files he wants and it generates that amount of fields (in this example 2), user fills the input fields and submits.

For some reason there is a input field inside of my input field and I can't figure out what I'm missing. I'm able to correctly get data from the input field, the form works correctly, I just don't want to have a field inside a field.

HTML:

        <div class="config-wrapper">
            <mat-form-field id="config-field">
                <div>
                    <mat-label>Number of configuration files</mat-label>
                </div>
                <mat-select formControlName="numberOfConfigPaths" (selectionChange)="onConfigChange($event)"
                    [ngClass]="{ 'is-invalid': isSubmitted && formControls.numberOfConfigPaths.errors }">
                    <option value=""></option>
                    <mat-option *ngFor="let number of configNumber" [value]="number.value">{{number.value}}</mat-option>
                </mat-select>
            </mat-form-field>
            <button type="button" mat-icon-button aria-label="Configuration path folder open" id="config-path-button"
                (click)="openConfigDialog();">
                <mat-icon>folder_open</mat-icon>
            </button>
        </div>


        <div *ngIf="isSubmitted && formControls.numberOfConfigPaths.errors" class="invalid-feedback">
            <div *ngIf="formControls.numberOfConfigPaths.errors.required">
                Number of configuration files is required
            </div>
        </div>

        <mat-form-field [formGroup]="cfg" class="example-full-width"
            *ngFor="let cfg of configPaths.controls; let i = index">
            <div class="config-container">
                <mat-form-field id="config-field">
                    <input type="text" matInput placeholder="Configuration file {{i+1}}"
                        formControlName="configPath"
                        [ngClass]="{ 'is-invalid': isSubmitted && cfg.controls.configPath.errors }"
                        [matAutocomplete]="comparisonAutoGroup" />
                    <mat-autocomplete #comparisonAutoGroup="matAutocomplete">
                        <mat-option *ngFor="let name of availableConfigFiles" [value]="name">
                            {{name}}
                        </mat-option>
                    </mat-autocomplete>
                </mat-form-field>

            </div>
            <div *ngIf="isSubmitted && cfg.controls.configPath.errors" class="invalid-feedback">
                <div *ngIf="cfg.controls.configPath.errors.required">Path is required</div>
            </div>
        </mat-form-field>

Relevant typescript:

  ngOnInit() {
    this.checkForm = this.formBuilder.group({
      numberOfConfigPaths: [1, Validators.required],
      configFilePaths: new FormArray([])
    });
    .
    .
    .
  }
  get formControls() { return this.checkForm.controls; }
  get configPaths() { return this.formControls.configFilePaths as FormArray; }

  onConfigChange(e) {
    const numberOfConfigPaths = e.value || 0;
    if (this.configPaths.length < numberOfConfigPaths) {
      for (let i = this.configPaths.length; i < numberOfConfigPaths; i++) {
        this.configPaths.push(
          this.formBuilder.group({
            configPath: ['', Validators.required]
          }
        ));
      }
    } else {
      for (let i = this.configPaths.length; i >= numberOfConfigPaths; i--) {
        this.configPaths.removeAt(i);
      }
    }
  }

While debugging I tried to isolate the field and make it only display 1 field (just copied the element somewhere else) and it worked fine, but I need to make it display multiple fields.

I'm stuck with finding the solution. I will reply if you need any additional info.

EDIT: Stackblitz URL: https://stackblitz.com/edit/angular-7bcgcw

Upvotes: 1

Views: 1046

Answers (2)

Darius Bogdan
Darius Bogdan

Reputation: 957

The problem in your code is that you have mat-form-field twice for each of the form controls, that is why it shows like that. I have removed the inner mat-form-field and now it looks ok. I have updated the solution to StackBlitz

It looks like this now:

enter image description here

Upvotes: 1

Michael
Michael

Reputation: 13

There is something called formArray it will solve your problem. Here is an example on medium here

Upvotes: 0

Related Questions