0

I am currently trying to make an input that is actually a different input for each letter in Angular 9. The problem I seem to be having currently is with change detection. The two ways that I see to do this are in conflict with each other. changes.subscribe() from @ViewChildren() doesn't update when I use a custom trackBy in my *ngFor, but I need the trackBy to prevent all kinds of issues with changes in one box propagating in another. I could use the custom trackBy function, but it cannot access data from my Component. Here is my component:

@Component({
  selector: 'app-multiple-fields',
  templateUrl: './multiple-fields.component.html',
  styleUrls: ['./multiple-fields.component.css'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      multi: true,
      useExisting: forwardRef(() => MultipleFieldsComponent),
    },
  ],
})
export class MultipleFieldsComponent
  implements OnInit, AfterViewInit, ControlValueAccessor {
  @Input() numFields: number = 6;
  @ViewChildren('input', { read: ElementRef }) inputs: QueryList<
    ElementRef
  >;
  fields: string[];

  onChange: any = () => {};
  onTouch: any = () => {};

  ngAfterViewInit() {
    this.inputs.changes.subscribe((next: QueryList<ElementRef>) => {
      let val = next.map((el) => el.nativeElement.value).join('');
      this.onChange(val);
      this.onTouch(val);
    });
  }

  ngOnInit() {
    this.fields = Array(this.numFields).fill('');
  }

  trackArray(index, item) {
    return index;
  }

  writeValue(value: string) {
    if (value.length == this.numFields) this.fields = value.split('');
  }

  registerOnChange(fn: any) {
    this.onChange = fn;
  }

  registerOnTouched(fn: any) {
    this.onTouch = fn;
  }
}

Here is the template for the component:

<input
  #input
  *ngFor="let item of fields; let i = index; trackBy: trackArray"
  [(ngModel)]="fields[i]"
/>

My hope is to be able to detect any changes in the fields[] array and then call onChange() and onTouch() with the joined value to be able to use [(ngModel)] on the component usage. Any help would be greatly appreciated. Thank you!

1 Answer 1

1

it's possible I don't understand what you are trying to do, but why aren't you using angular change?

<input *ngFor="let item of fields" (change)="itemChanged(item)">
Sign up to request clarification or add additional context in comments.

1 Comment

🤦‍♂️I'm so sorry, I didn't know this was a thing. Thank you so much!

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.