Angular form patch value with child component

Viewed 48

I want to implement form for my expenses tracking app. This form includes name, price, date, and category. The categories list is unique for each individual user, so I perform API request to get all the categories user has. Special component is responsible for this job in front-end :

@Component({
  selector: 'app-category-select',
  templateUrl: './category-select.component.html',
  styleUrls: ['./category-select.component.css'],
  providers: [     
    {       provide: NG_VALUE_ACCESSOR, 
            useExisting: forwardRef(() => CategorySelectComponent),
            multi: true     
    }   
    ]
})
export class CategorySelectComponent implements OnInit, ControlValueAccessor  {

  categories: Category[] = [];
  @Input() parentForm! : FormGroup;
  @Output() categoryEvent = new EventEmitter<number>();
  catId!: number
  categoryId!: number

  constructor(private categoryService: CategoriesService) {}

  onChange: any = () => {}

  onTouch: any = () => {}

  setCatId(categoryId: number){
    if( categoryId !== undefined && this.categoryId !== categoryId){
      this.categoryId = categoryId
      this.onChange(categoryId)
      this.onTouch(categoryId)
    }
  }

  writeValue(obj: any): void {
    this.catId = obj
  }
  registerOnChange(fn: any): void {
    this.onChange = fn
  }
  registerOnTouched(fn: any): void {
    this.onTouch = fn
  }
  setDisabledState?(isDisabled: boolean): void {

  }
  constructor(private categoryService: CategoriesService) {}

  ngOnInit(): void {
    
    this.categoryService.findAll(parseInt(localStorage.getItem(environment.userIdName) || '')).subscribe(
      result => this.categories = result
    )
  }

  changeCategory(categoryId: number){
    this.categoryEvent.emit(categoryId)
  }
}
...

<mat-form-field appearance="fill" *ngIf="parentForm" [formGroup]="parentForm">
    <mat-label>Select category</mat-label>
      <mat-select #categoryId [formControlName]="'category'" [(ngModel)] = "catId">
        <mat-option *ngFor="let category of categories" value="{{category.id}}">{{category.name}}</mat-option>
 </mat-select>
</mat-form-field>

This component is a part of my main form for adding or editing expenses:

<form  [formGroup]="form" (ngSubmit)="onSubmit()">
...
<div class="input-field">
  <app-category-select [parentForm]="form"></app-category-select>
</div>
</form>

And ts-file:

this.form = new FormGroup({
      name: new FormControl(null, Validators.required),
      price: new FormControl(null, [Validators.required, Validators.pattern('[0-9]+(\.[0-9][0-9]?)?')]),
      category: new FormControl(null, Validators.required),
      date: new FormControl(null, Validators.required)
    })

The problem: When I'm trying to edit expense using form.patchValue() and updateTextFields() from materialize library I want all fields to display the current expenses data. But it updates all fields except the categories:

if(expense){
            this.expense = expense
            this.form.patchValue({
              name: expense.name,
              price: expense.price,
              date: new Date(expense.date),
              category: expense.categoryDTO.id
            })
            MaterialsService.updateTextInputs()
          }

Form itself includes the category value, but how to get it in view?

0 Answers
Related