Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 - Setting date field on reactive form

I have a component that uses two date fields, a start date & and end date.

By default, I have my end date field disabled and I toggle it when they select a start date.

this.transitionForm = this.fb.group({
 effectiveEndDate: [{ value: '', disabled: true }]
 ..... 
});

I am trying to set the value of this end date field within my code.

this.transitionForm.controls['effectiveEndDate'].setValue(this.utils.currentDate());

Utility Function:

/**
 * Returns the current date
 */
currentDate() {
    const currentDate = new Date();
    const day = currentDate.getDate();
    const month = currentDate.getMonth() + 1;
    const year = currentDate.getFullYear();
    return month + "/" + day + "/" + year;
}

HTML:

<input type="date" class="form-control input-sm" id="effectiveEndDate" name="effectiveEndDate" placeholder="Required" formControlName="effectiveEndDate">

For some reason, the field is not getting updated though.

I have also tried to use PatchValue and that wasn't setting it either.

What am I missing?

like image 932
SBB Avatar asked Jul 26 '17 14:07

SBB


2 Answers

When you run this code in Chrome (other browsers not tested) it logs an error to console:

The specified value "7/26/2017" does not conform to the required format, "yyyy-MM-dd".

Which I think describes the problem pretty well

You can fix it by changing your currentDate() method to something like:

currentDate() {
  const currentDate = new Date();
  return currentDate.toISOString().substring(0,10);
}

Live plunker example

While this does fix the problem the answer from @JGFMK shows a better way of converting the date using a DatePipe

like image 102
0mpurdy Avatar answered Oct 05 '22 03:10

0mpurdy


Angular has several ways to work with and manage forms. Not all the methods or even all configurations will show a value in the view. I have tried several options and my favorite by far is a reactive form configured like this, as it is simple, clean, flexible, supports validation and will show values in the view.

In your component you need to import FormBuilder and FormGroup from @angular/forms. Optionally you can import Validators as a way to validate each form field.

import { FormBuilder, FormGroup, Validators } from '@angular/forms';

In the rest of the component we need to define a new variable of type FormGroup: transitionForm: FormGroup.

Then we need to use constructor injection to make fb available as FormBuilder: constructor(public fb: FormBuilder), and add field names to our FormBuilder variable: this.transitionForm = fb.group({ ... });

export class EgComponent implements OnInit {
  transitionForm: FormGroup;

  constructor(public fb: FormBuilder) {
    this.transitionForm = fb.group({
      'effectiveEndDate': [''],
      ...
    });
  }
  ...
}

You can set the date in many ways. Here we'll just set it using ngInit

ngOnInit() {
  const currentDate = new Date().toISOString().substring(0, 10);
  this.transitionForm.controls['transitionForm'].setValue(currentDate);
}

For your form you just need is:

<form (ngSubmit)="onSubmit(transitionForm)" [formGroup]="transitionForm" novalidate>
  <input type="date" formControlName="effectiveEndDate">
  ...
  <button type="submit" [disabled]="transitionForm.invalid">Submit</button>
</form>

Because this method uses ReactiveForms you need to make sure to add it to @NgModule

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...,
    FormsModule,
    ReactiveFormsModule
  ],
...

Besides making data visible in the view, doing it this way also allows for cleaner html form layout and simple validation. You completely eliminate the need for ngModel and form name tags.

You can pass data to your method directly (ngSubmit)="onSubmit(transitionForm)" and since it's a FormGroup your forms data is also available as this.transitionForm.value

like image 21
Jared Whipple Avatar answered Oct 05 '22 03:10

Jared Whipple