ngneat / reactive-forms

(Angular Reactive) Forms with Benefits 😉
https://www.netbasal.com
611 stars 56 forks source link

How do I get the FormGroup's value, not the ControlsValue #99

Closed grosch closed 3 years ago

grosch commented 3 years ago

I'm submitting a...

[X] Support request

Current behavior

A FormGroup's value$ observable emits a ControlsValue<T> instead of a T.

Expected behavior

I want to actually get a value of type T so that I can do this:

this.formGroup.value$.pipe(
    takeUntil(this.unsubscribe$),
).subscribe(x => {
    this.onTouch?.()
    this.onModelChange?.(x)
})

That doesn't work though because x there isn't actually of type T

I'm doing nested forms, and so when this form changes, I pass the value up to the parent's control.

Environment

Angular version: 12.1.2


Browser:
- [ X] Chrome (desktop) version XX

For Tooling issues:
- Node version: v12.19.0
- Platform:  Windows 10
NetanelBasal commented 3 years ago

Please reproduce on stackblitz

grosch commented 3 years ago

I tried to create a stackblitz for you but that doesn't work as ngcc fails to run against @ngneat/reactive-forms now. However, I was able to simplify it down to this example that will show the failure if you paste it into your project:

export abstract class DetailForm<T> implements OnInit {
  formGroup!: FormGroup<T>
  public onChange?: (x: T | null) => void

  ngOnInit(): void {
    this.formGroup.value$.subscribe(x => {
      this.onChange?.(x)
    })
  }
}
grosch commented 3 years ago

Any help you can provide here?

grosch commented 3 years ago

@NetanelBasal Any updates? I'd love to reproduce on stackblitz but if I add @ngneat/reactive-forms then ngcc fails there.

NetanelBasal commented 3 years ago

You can use codesandbox

grosch commented 3 years ago

OK, I found that my CVA was conflicting with your ControlValueAccessor, and that's why I was getting that specific error. The other one I'm getting, which is a similar issues with the ControlsValue thing can be seen here: https://codesandbox.io/s/dreamy-pateu-l7gul?file=/src/app/abstract-detail-form.ts

NetanelBasal commented 3 years ago

Try this:

import { Directive } from "@angular/core";
import { FormGroup, ControlValueAccessor, } from "@ngneat/reactive-forms";
import { ControlsValue } from "@ngneat/reactive-forms/lib/types";

@Directive()
export abstract class AbstractDetailForm<T extends Record<any, any>> extends ControlValueAccessor<T> {
  public abstract readonly formGroup: FormGroup<T>;

  writeValue(obj: ControlsValue<T> | null | undefined): void {
    if (obj)
     this.formGroup.setValue(obj);
  }
}
NetanelBasal commented 3 years ago

ControlsValue is now exported in v2.