Angular FormControl - click twice to make validation work

58 Views Asked by At

I'm trying to create my own todo form and it came dowm to validating input of single todo item. Somehow validation doesn't work correctly, it works only if I focus the input, click outside of it, then foucs it once again and then click outside once again. Can somebody, please, explain, me what I'm missing here? I know it's possible to rewrite the code, but would be grateful to understand the reason of such behaviour.

enter image description here

By commenting out different parts of code, I've reached out that if I delete (updateTodoChildEvent)="updateTodo($event)" from todo-item.component.html validation works correctly, but I don't know why.

todo-item.component.ts

import {Component, ElementRef, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {FormControl, FormGroup, Validators, FormBuilder} from "@angular/forms";
import {Todo} from "../todo";
import {TodoService} from "../todo.service";

@Component({
  selector: 'app-todo-item',
  templateUrl: './todo-item.component.html',
  styleUrls: ['./todo-item.component.css']
})
export class TodoItemComponent {
  @Input() todoItemsList: Todo[] = [];
  @Input() todoItem!: Todo;
  @Output() updateTodoEvent = new EventEmitter<Todo>();

  constructor(private todoService: TodoService) {
  }

  updateTodo(todo: Todo) {
    this.updateTodoEvent.emit(todo);
  }
}

todo-item.component.html

<div>
    <form>
      <app-todo-edit
        [todoItemChild]="todoItem"
        (updateTodoChildEvent)="updateTodo($event)"
      >
      </app-todo-edit>
    </form>
</div>

todo-edit.component.ts

import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {Todo} from "../todo";
import {FormControl, FormGroup, Validators} from "@angular/forms";

@Component({
  selector: 'app-todo-edit',
  templateUrl: './todo-edit.component.html',
  styleUrls: ['./todo-edit.component.css']
})
export class TodoEditComponent implements OnInit {
  @Output() updateTodoChildEvent = new EventEmitter();
  @Input() todoItemChild!: Todo;

  formControlChild = new FormControl('', [Validators.required, Validators.minLength(3)])

  ngOnInit() {
    this.formControlChild.setValue(this.todoItemChild.name);
  }

  onChildInputChange(todo: Todo, val: string) {
    this.updateTodoChildEvent.emit({id: todo.id, name: val});
  }

  getErrorMessage() {
    if (this.formControlChild.hasError('required')) {
      return 'You must enter a value';
    }

    return this.formControlChild.hasError('minlength') ? 'Too short, should be at least 3 symbols' : '';
  }
}

todo-edit.component.html

<form>
  <mat-form-field>
    <mat-label>Edit Todo</mat-label>
    <input
      matInput
      type="text"
      #inputRef
      (change)="onChildInputChange(todoItemChild, inputRef.value)"
      [formControl]="formControlChild"
    >
    <mat-error *ngIf="formControlChild.invalid">{{getErrorMessage()}}</mat-error>
  </mat-form-field>
</form>
0

There are 0 best solutions below