skip to Main Content

I have tried everything on StackOverflow similar questions but still I couldn’t fix this issue.

I have this method in my component.ts file.

private initForm() {
    if (this.form) {
        this.form.patchValue(this.course);

    } else {

        var controlsConfig = {
            duration: [this.course.duration],
            credits: [this.course.credits],
            expires: [],
            comment: [this.course.comment]
        };

        // adding custom fields to course controls
        for (var i = 0; i < this.courseCustomFields.length; i++) {
            controlsConfig[this.courseCustomFields[i].key] = [this.course[this.courseCustomFields[i].key]];
        }

        this.form = this.formBuilder.group(controlsConfig);
    }

And I have populated the custom field input fields in my component.html like below.

<div class="row" *ngFor="let courseCustomFieldRow of courseCustomFieldsForFront">
     <div class="col-md-3" *ngFor="let courseCustomField of courseCustomFieldRow">
         <div class="form-group">
              <label>{{courseCustomField.title}}</label>
              <input type="text" class="form-control" [formControlName]="courseCustomField.key">
         </div>
     </div>
</div>

But still it loses focus when I type one character.

2

Answers


  1. I am not able to replicate your issue, below is a stackblitz for the same! try adding track by for the ngFor it might stop the lists from re-rendering!

    If your issue is not resolved please share back the stackblitz with the issue replicated!

    ts

    import { CommonModule } from '@angular/common';
    import { Component } from '@angular/core';
    import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
    import { bootstrapApplication } from '@angular/platform-browser';
    import 'zone.js';
    
    @Component({
      selector: 'app-root',
      standalone: true,
      imports: [CommonModule, ReactiveFormsModule],
      template: `
        <form [formGroup]="form">
          <div class="row" *ngFor="let courseCustomFieldRow of courseCustomFieldsForFront;trackBy:trackByKey">
              <div class="col-md-3" *ngFor="let courseCustomField of courseCustomFieldRow;trackBy:trackByKey">
                  <div class="form-group">
                        <label>{{courseCustomField.title}}</label>
                        <input type="text" class="form-control" [formControlName]="courseCustomField.key">
                  </div>
              </div>
          </div>
        </form>
      `,
    })
    export class App {
      form!: FormGroup;
      name = 'Angular';
      course: any = {
        duration: 1,
        credits: 15,
        comments: 'asdf',
      };
      courseCustomFields: any = [
        { key: 'duration', title: 'Duration' },
        { key: 'credits', title: 'Credits' },
        { key: 'comment', title: 'Comment' },
      ];
    
      constructor(private formBuilder: FormBuilder) {}
    
      ngOnInit() {
        this.initForm();
      }
    
      trackByKey = (index: number, obj: object): number => {
        return index;
      };
    
      get courseCustomFieldsForFront() {
        return [this.courseCustomFields];
      }
    
      private initForm() {
        if (this.form) {
          this.form.patchValue(this.course);
        } else {
          const controlsConfig: any = {
            duration: [this.course.duration],
            credits: [this.course.credits],
            expires: [],
            comment: [this.course.comment],
          };
    
          // adding custom fields to course controls
          for (var i = 0; i < this.courseCustomFields.length; i++) {
            controlsConfig[this.courseCustomFields[i].key] = [
              this.course[this.courseCustomFields[i].key],
            ];
          }
          console.log(controlsConfig);
          this.form = this.formBuilder.group(controlsConfig);
        }
      }
    }
    
    bootstrapApplication(App);
    

    Stackblitz Demo

    Login or Signup to reply.
  2. Generally this behavior is because you’re iterating over an array and the "input" change the array (so Angular must render it again). This is the reason, e.g. iterate in a FormArray over the formArray.controls, or use trackBy, or use an auxiliar array than not change (e.g. we can create this.aux=this.array.map((x,index)=>index) and iterate over "aux" instead of this.array. But I don’t know this case in your code 🙁

    Three more ideas:

    1. I can not understand this[ ] in your code

         [this.course[this.courseCustomFields[i].key]]
         //it's not? 
         this.course[this.courseCustomFields[i].key]
      

      else you’re assign an array! to the control value (if you have
      an input tag has no sense)

    2. NOT use "var" else "let" or "const". var create a variable global in your aplication, let

        var controlsConfig={....}
        //replace by
        const controlsConfig={....} //if the variable don't change inside the function
        let controlsConfig={....} //if the variable change inside the function
      
    3. It’s possible you want to use a FormArray of FormGroups instead of
      an array of FormGroups?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search