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

4
  • create a stackbliz please Commented Oct 2, 2018 at 19:45
  • You need to add a trackBy function to your ngFor to prevent that issue. See first answer of stackoverflow.com/questions/42322968/… Commented Oct 2, 2018 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 ? Commented Oct 3, 2018 at 12:05
  • Do you have a stackblitz of what you tried so far? Try taking a look at stackoverflow.com/questions/45973025/… Commented Oct 3, 2018 at 13:47

1 Answer 1

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;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Works Perfectly !.. Thanks for the link explaining the issue too. Much Appreciated :)

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.