Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 reactive forms - piping a value from a formControlName

Using Angular 2, I have a parameter called "example" that is a Date object. In the template I want to format "example" with a date pipe. Something like this:

<input type="text" [value]="example | date:'shortTime'">
// 9:00 AM 

However, I need to use Angular's reactive forms. FormControls take precedent, so formControlName will override anything in the value directive.

<input type="text" formControlName="example">
// Wed Mar 08 2017 09:00:00 GMT-0700 (MST)

<input type="text" formControlName="example" [value]="example | date:'shortTime'">
// Wed Mar 08 2017 09:00:00 GMT-0700 (MST)

The formControlName directive will not accept pipes. How can I format a Date object in the template of a reactive form?

Pseudo-code:

@Component({
    template: `
        <form [formGroup]="formGroup">
            Example: <input type="text" formControlName="example">
        </form>
    `
})

export class ExampleComponent implements OnInit {
    public formGroup: FormGroup;
    public example: Date = new Date();

    public ngOnInit() {
        this.formGroup = new FormGroup({
            example: new FormControl(this.example)
        });
    }
}
like image 200
ebakunin Avatar asked Mar 08 '17 17:03

ebakunin


1 Answers

UPDATE: I realized a simpler, more sensible approach uses valueChanges to perform a setValue with a pipe transform on the change event value.

There are probably some best practices to find about cleaning up subscriptions and being efficient if you have many form controls with subscriptions. You could also clean up any unwanted pipe transformations when you process/submit the final form values.

Basic example (See also: original source):

ngOnInit() {
  this.searchField = new FormControl();
  this.searchField.valueChanges
      .subscribe(val => {
        this.searchField.setValue(myPipe.transform(val))
      });
}

Excerpt with debounce delay + distinctness check (provided by RxJS pipeable operators):

this.searchField.valueChanges
    .pipe( // RxJS pipe composing delay + distinctness filters
        debounceTime(400),
        distinctUntilChanged()
    )
    .subscribe(term => {
      this.searchField.setValue(myPipe.transform(val))
  });

Original suggestion...

This answer describes how to create a custom control value accessor for an input field that inserts customized timestamp conversion functions inside the onChange (which gets the convertTo* custom function) and writeValue (which gets the convertFrom custom function) methods.

You would likely create something similar (e.g. adapt template etc. to other form input types) but replace the conversion functions with your desired Pipe transform methods (probably two different types) to achieve what you are after. Angular documentation or source code could be helpful for further details.

I think other suggested approaches here involving a pipe transform during the initial form control creation, are more limited and possibly not what you're expecting because it won't continue to apply those changes as the input value is changed by the user. It would display correctly at first but any manipulation would lose the transform filtering and the form would simply be submitted as is without the pipe transform applied.

I may be missing something about how the other suggestions work or specifically what you're after.

like image 179
jmmygoggle Avatar answered Nov 15 '22 05:11

jmmygoggle