1

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

2
  • Could you provide a stackBlitz example such that it's easier to debug? Commented Mar 24, 2020 at 18:45
  • Hi @DariusBogdan, I've put it on stackblitz now: stackblitz.com/edit/angular-7bcgcw Sorry if there are some beginner mistakes, I've just recently started my angular Javascript journey. Thanks for taking the time to reply! Commented Mar 25, 2020 at 19:44

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

1 Comment

I can't believe this slipped by me, I was so confused. Thank you very much kind sir!
0

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

1 Comment

Hi, thanks for taking time to reply, but I have used formArray here. Maybe I'm not using it correctly? I've uploaded it to stackblitz if it can be of some help: stackblitz.com/edit/angular-7bcgcw

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.