1


I am trying to work on a form which requires adding some dynamic fields in it. I am storing these dynamic entries within an array. The problem is when I bind my input field with Ng-Model, its only allowing me to enter one character at a time.

i.e. if I try to enter for e.g. 'test', i am only able to enter 't' , to enter the next character, i have to again click on the input field and then enter the next character. Things work fine without ngModel but i need to use ngModel in order for my scenario to work. Below is the code :

HTML:

<form #personalForm="ngForm" class="editForm" novalidate>
    <tbody>
        <tr *ngFor="let value of personal.array; let i = index">
            <td>
                <div class="input-group">
                    <div class="input-group-prepend">
                        <div (click)="deleteFieldValue(i)" class="input-group-text"><i class="mdi mdi-close mdi-18px"></i></div>
                    </div>
                    <input type="text" class="form-control input-md" [(ngModel)]="personal.array[i]" name="{{[i]}}" placeholder="item name">
                </div>
            </td>
        </tr>
        <tr>
            <td align="right">
                <button class="btn btn-success btn-sm" type="button" (click)="addFieldValue()" style="margin-right:10px">Add More Item</button>
                <button (click)="onEditCloseItems()" class="btn btn-primary btn-sm" type="button">Save Items</button>
            </td>
        </tr>
    </tbody>
</form>

TypeScript:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { FormGroup, FormControl, FormArray, Validators } from '@angular/forms';
import { Personal } from '../data/formData.model';
import { FormDataService } from '../data/formData.service';

@Component({
    selector: 'app-personal',
    templateUrl: './personal.component.html'
})

export class PersonalComponent implements OnInit {

    personal: Personal;
    form: any;
    newAttribute = '';
    isEditItems: boolean;

    constructor(private router: Router, private formDataService: FormDataService) { }

    ngOnInit() {
        this.personal = this.formDataService.getPersonal();
        console.log('Personal feature loaded!');
    }

    save(form: any): boolean {
        if (!form.valid) {
            return false;
        }

        this.formDataService.setPersonal(this.personal);
        return true;
    }

    goToNext(form: any) {
        if (this.save(form)) {
            // Navigate to the work page
            this.router.navigate(['/work']);
        }
    }

    addFieldValue() {
        if (this.personal.array.length <= 8) {
            this.personal.array.push(this.newAttribute);
        } else {

        }
    }

    deleteFieldValue(index) {
        this.personal.array.splice(index, 1);
    }

    onEditCloseItems() {
        this.isEditItems = !this.isEditItems;
    }
}

formModel.ts file :

export class Personal {
    firstName: string = '';
    lastName: string = '';
    email: string = '';
    array: string[] = [];
}

Below is the screenshot of the form:
enter image description here

The problem here is in the dynamic input text fields for the array, I am only able to enter a single alphabet in those fields. To enter the next alphabet, i have to again click on the input field, Can anybody please explain as to why does this happen and provide a solution please.

Thank You

Gaspar
  • 1,515
  • 13
  • 20
nemish nigam
  • 65
  • 2
  • 10
  • create a stackbliz please – Patricio Vargas Oct 02 '18 at 19:45
  • You need to add a `trackBy` function to your ngFor to prevent that issue. See first answer of https://stackoverflow.com/questions/42322968/angular2-dynamic-input-field-lose-focus-when-input-changes – angtlin Oct 02 '18 at 21:01
  • @angtlin How will i modify this use case if I am having key value pairs in my array e.g. array:[{name:string,phone:string}]. how can I modify my ng-model bindings to map values to these keys instead ? – nemish nigam Oct 03 '18 at 12:05
  • Do you have a stackblitz of what you tried so far? Try taking a look at https://stackoverflow.com/questions/45973025/angular-2-model-binding-array-of-object – angtlin Oct 03 '18 at 13:47

1 Answers1

3

Stackblitz example

Add trackBy to your HTML:

<tr *ngFor="let value of personal.array; let i = index; trackBy: trackByFn">

Add to your TypeScript:

trackByFn(index: any, item: any) {
    return index;
}
angtlin
  • 192
  • 1
  • 9