-2

Angular 5.2.4 - reactive form with failing date pipe despite reset()

I am creating a dynamically generated reactive form. There is a single control in my example, which displays a date. The date should be formatted by the date pipe (in the template), and does so correctly, the first time that the form builds. However, in successive form builds, the date is rendered as a date string without formatting applied by the pipe.

In each form build, I call FormGroup.reset(), and have also tried setting the FormGroup to null.

Edit: After this was answered, I moved the pipe trnasformation into the .ts file. This will work for many situations, though there are situations where it is not working in more complex generated forms. So for many, this solution will work.

I have included my code below, and clearly marked the changes I made after receiving an answer. A Stackblitz link is also found with this same code at the bottom of this post.

Here is the .ts code I started with (I have noted my changes in comments):

import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
// ***added this DatePipe import after the answer***
import { DatePipe } from '@angular/common'; 

@Component({
  selector: 'material-app',
  templateUrl: 'app.component.html',
  styleUrls: ['./app.component.css'],
   // ***added following line after the answer***
  providers: [DatePipe]
})
export class AppComponent {
  formGroup: FormGroup;
  importantDate = "2018-08-22T12:34:56.789Z";
  anotherDate = "2015-11-00T01:23:45.678Z";
  test = 0;

 // *** added DatePipe injection to constructor after answer***
  constructor(private datePipe: DatePipe) { }

  ngOnInit() {
    this.buildForm(this.importantDate);
  }

 // ***added this function after the answer***
  transformDate(date) {
    return this.datePipe.transform(date, 'MM/dd/yyyy');
  }

  // build the form the first time
  buildForm(dateValue) {
    this.formGroup = new FormGroup({
      dateEnjoined: new FormControl(this.importantDate)
 /**NOTE: alternatively, "dateEnjoined: new FormControl(this.transformDate(dateValue))" would 
also work here. But the template pipe handles the first transformation OK.*/
    });
  }

// this is my original function to rebuild the form
  unSetAndRebuildForm_OLD_VERSION() {
    if (this.formGroup.get('dateEnjoined').value == this.anotherDate) {
      this.formGroup.reset({ dateEnjoined: this.importantDate });
      this.test = 0;
    } else {
      this.formGroup.reset({ dateEnjoined: this.anotherDate });
      this.test = 1;
    }
  }

// *** I altered the function to this version, after the answer***
  unSetAndRebuildForm() {
    if (this.test == 1) {
      this.formGroup.reset();
      this.formGroup.patchValue({ dateEnjoined: this.transformDate(this.importantDate) });
      this.test = 0;
    } else {
      this.formGroup.reset();
      this.formGroup.patchValue({ dateEnjoined: this.transformDate(this.anotherDate) });
      this.test = 1;
    }
  }
}

Here is the .html code for the form (required no changes). I have left the date pipe in the form (so far, this does not break, and allows the form to reflect updated values if they are received from the server, without forcing a form rebuild). Also, note that I did leave the brackets [] around "value":

<form class="basic-container" [formGroup]="formGroup">
  <input formControlName="dateEnjoined" 
  [value]="importantDate |  date: 'MM/dd/yyyy'">
  <button (click)="unSetAndRebuildForm()">  click me </button>
</form>

After the answer, in my AppModule.ts, I also needed to both importDatePipe and add it to the providers array (in the actual application, I made these changes in SharedModule):

import { DatePipe } from '@angular/common';

providers: [ DatePipe ]

https://stackblitz.com/edit/ang5-date-pipe-fails-after-first-build

sboggs11
  • 178
  • 1
  • 12

1 Answers1

2

We can call datepipe from component end too. Also, we need to import DatePipe as component providers

    import { DatePipe } from '@angular/common';

    @Component({
      selector: 'material-app',
      templateUrl: 'app.component.html',
      styleUrls: ['./app.component.css'],
      providers: [DatePipe]
    })

    transformDate(date) {
      return this.datePipe.transform(date, 'MM/dd/yyyy');
    }

    unSetAndRebuildForm() {
        if (this.formGroup.get('dateEnjoined').value == this.anotherDate) {
          this.formGroup.reset();
          // console.log(this.transformDate(this.importantDate));
          // alert(this.transformDate(this.importantDate));
          this.formGroup.patchValue({ dateEnjoined: this.transformDate(this.importantDate) });
          this.test = 0;
        } else {
          this.formGroup.reset();
          // console.log(this.transformDate(this.anotherDate));
          // alert(this.transformDate(this.anotherDate));
          this.formGroup.patchValue({ dateEnjoined: this.transformDate(this.anotherDate) });
          this.test = 1;
        }
      }

Also please remove [value] from template file.

Suresh Kumar Ariya
  • 9,516
  • 1
  • 18
  • 27
  • I think this will work in my dynamic form. In unsetAndRebuildForm(), if you change the test to `if (this.test == 0)`, you can reset the form endlessly. Let me test a little bit more, and will mark as the correct answer barring the unseen. Thanks! – sboggs11 Aug 07 '18 at 02:56