Search code examples
angularangular-ngmodel

Cannot bind an array with ngModel in angular because the index is read-only


<div *ngFor="let x of options; let i = index;trackBy:trackByIdx">
    <mat-form-field class="full-width" appearance="fill">
        <mat-label>Option</mat-label>
        <input type="input" [(ngModel)]="options[i]" matInput>
    </mat-form-field>
</div>

For some odd reason, I am getting an error from the template when trying to edit the quiz form. I am getting ERROR TypeError: 0 is read-only from [(ngModel)]="options[i]", which means the error comes from the template.

@Input() title: string;
@Input() options: string[];
@Output() titleEmitter: EventEmitter<string> = new EventEmitter<string>();
@Output() optionsEmitter: EventEmitter<string[]> = new EventEmitter<string[]>();
  
onAddOptions() {
    if (this.options && this.options.length < 11) {

      this.optionsEmitter.emit([...this.options, '']);
    }
}
  
emitOptions(index: number) {
    this.optionsEmitter.emit([...this.options.slice(0, index), this.options[index], ...((this.options[index+1]) ? this.options.slice(index + 1) : [])])
}

I am not sure if the rest of the code will work as intended, because the error is thrown from the template, but I am hoping to understand why it's throwing an error. Is the index read only? It seems to be coming from the index, because I also get ERROR TypeError: 1 is read-only when I try to edit the second option.


Solution

  • there is no need to use index in ngModel. AS I am able to see you just have to bind the input with the value using the for loop.

    You can just replace your html code with the following code of lines. This will eliminate your error and you can achieve the same you want.

    <div *ngFor="let x of options; let i = index;trackBy:trackByIdx">
        <mat-form-field class="full-width" appearance="fill">
            <mat-label>Option</mat-label>
            <input type="input" [(ngModel)]="x" matInput>
        </mat-form-field>
    </div>